Разные пользователи не могут одновременно использовать мое приложение WinForms

У меня есть приложение VS WinForms, которое использует OleDB для чтения (только чтение, без записи) информации из файла Excel. Мои конечные пользователи устанавливают программу с помощью однократного щелчка, созданного с помощью параметра публикации в сообществе Visual Studio. Установка работает нормально. НО: одновременно использовать программу может только один пользователь. Windows выдает мне эту ошибку:

Files that may help descibe the problem:
  C:\Users\shoo\AppData\Local\Temp\WERA825.tmp.WERInternalMetadata.xml
  C:\Users\shoo\AppData\Local\Temp\WERDFAA.tmp.appcompat.txt
  C:\Users\shoo\AppData\Local\Temp\WERE18F.tmp.mdmp

Все файлы содержат одну и ту же информацию:

    <?xml version="1.0" encoding="UTF-16"?>
<DATABASE>
<EXE NAME="Streetlife Database Lookup.exe" FILTER="CMI_FILTER_PRIVACY">
    <MATCHING_FILE NAME="lcpi.data.oledb.net4.dll" SIZE="841728" CHECKSUM="0x4AEF1CA6" BIN_FILE_VERSION="1.0.1.2490" BIN_PRODUCT_VERSION="1.0.1.2490" PRODUCT_VERSION="1.0.1.2490" FILE_DESCRIPTION="LCPI ADO.NET Data Provider for OLE DB [NET4]" COMPANY_NAME="LCPI" PRODUCT_NAME="lcpi.data.oledb" FILE_VERSION="1.0.1.2490" ORIGINAL_FILENAME="lcpi.data.oledb.net4.dll" INTERNAL_NAME="lcpi.data.oledb.net4.dll" LEGAL_COPYRIGHT="Copyright © LCPI 2011-2015" VERDATEHI="0x0" VERDATELO="0x0" VERFILEOS="0x4" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0xD742F" LINKER_VERSION="0x0" UPTO_BIN_FILE_VERSION="1.0.1.2490" UPTO_BIN_PRODUCT_VERSION="1.0.1.2490" LINK_DATE="08/06/2015 14:05:40" UPTO_LINK_DATE="08/06/2015 14:05:40" VER_LANGUAGE="Taalonafhankelijk [0x0]" EXE_WRAPPER="0x0" />
    <MATCHING_FILE NAME="lcpi.lib.net4.dll" SIZE="347136" CHECKSUM="0x3345E399" BIN_FILE_VERSION="1.0.0.1224" BIN_PRODUCT_VERSION="1.0.0.1224" PRODUCT_VERSION="1.0.0.1224" FILE_DESCRIPTION="LCPI Instrumental Library for .NET 4" COMPANY_NAME="LCPI" PRODUCT_NAME="lcpi.lib" FILE_VERSION="1.0.0.1224" ORIGINAL_FILENAME="lcpi.lib.net4.dll" INTERNAL_NAME="lcpi.lib.net4.dll" LEGAL_COPYRIGHT="Copyright © LCPI 2011-2015" VERDATEHI="0x0" VERDATELO="0x0" VERFILEOS="0x4" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x5AFBE" LINKER_VERSION="0x0" UPTO_BIN_FILE_VERSION="1.0.0.1224" UPTO_BIN_PRODUCT_VERSION="1.0.0.1224" LINK_DATE="08/06/2015 14:05:39" UPTO_LINK_DATE="08/06/2015 14:05:39" VER_LANGUAGE="Taalonafhankelijk [0x0]" EXE_WRAPPER="0x0" />
    <MATCHING_FILE NAME="Microsoft.VisualStudio.OLE.Interop.dll" SIZE="118784" CHECKSUM="0xE2A9E029" BIN_FILE_VERSION="7.10.6070.0" BIN_PRODUCT_VERSION="7.10.6070.0" PRODUCT_VERSION="7.10.6070" FILE_DESCRIPTION="" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Microsoft® Visual Studio .NET" FILE_VERSION="7.10.6070" ORIGINAL_FILENAME="" INTERNAL_NAME="" LEGAL_COPYRIGHT="Copyright© Microsoft Corporation.  All rights reserved." VERDATEHI="0x0" VERDATELO="0x0" VERFILEOS="0x4" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x2C347" LINKER_VERSION="0x0" UPTO_BIN_FILE_VERSION="7.10.6070.0" UPTO_BIN_PRODUCT_VERSION="7.10.6070.0" LINK_DATE="08/24/2009 12:53:35" UPTO_LINK_DATE="08/24/2009 12:53:35" VER_LANGUAGE="Engels (Verenigde Staten) [0x409]" EXE_WRAPPER="0x0" />
    <MATCHING_FILE NAME="Streetlife Database Lookup.exe" SIZE="125376" CHECKSUM="0x5042252" BIN_FILE_VERSION="1.0.0.0" BIN_PRODUCT_VERSION="1.0.0.0" PRODUCT_VERSION="1.0.0.0" FILE_DESCRIPTION="WindowsFormsApplication1" COMPANY_NAME="Streetlife" PRODUCT_NAME="Streetlife Databse Lookup" FILE_VERSION="1.0.0.0" ORIGINAL_FILENAME="Streetlife Database Lookup.exe" INTERNAL_NAME="Streetlife Database Lookup.exe" LEGAL_COPYRIGHT="Copyright © SHOO;-)" VERDATEHI="0x0" VERDATELO="0x0" VERFILEOS="0x4" VERFILETYPE="0x1" MODULE_TYPE="WIN32" PE_CHECKSUM="0x2CFAE" LINKER_VERSION="0x0" UPTO_BIN_FILE_VERSION="1.0.0.0" UPTO_BIN_PRODUCT_VERSION="1.0.0.0" LINK_DATE="08/27/2015 10:24:53" UPTO_LINK_DATE="08/27/2015 10:24:53" VER_LANGUAGE="Taalonafhankelijk [0x0]" EXE_WRAPPER="0x0" FILE_ID="00005974d6b5b0b5a80644936a6ef12feedfa35a97e3" PROGRAM_ID="0000da39a3ee5e6b4b0d3255bfef95601890afd80709" />
</EXE>
<EXE NAME="KERNELBASE.dll" FILTER="CMI_FILTER_THISFILEONLY">
    <MATCHING_FILE NAME="KernelBase.dll" SIZE="424448" CHECKSUM="0xBE7BDE30" BIN_FILE_VERSION="6.1.7601.18939" BIN_PRODUCT_VERSION="6.1.7601.18939" PRODUCT_VERSION="6.1.7601.18015" FILE_DESCRIPTION="DLL-bestand voor Windows NT BASE API-client" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Besturingssysteem Microsoft® Windows®" FILE_VERSION="6.1.7601.18015 (win7sp1_gdr.121129-1432)" ORIGINAL_FILENAME="Kernelbase" INTERNAL_NAME="Kernelbase" LEGAL_COPYRIGHT="© Microsoft Corporation. Alle rechten voorbehouden." VERDATEHI="0x0" VERDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x70CFC" LINKER_VERSION="0x60001" UPTO_BIN_FILE_VERSION="6.1.7601.18939" UPTO_BIN_PRODUCT_VERSION="6.1.7601.18939" LINK_DATE="07/22/2015 23:59:55" UPTO_LINK_DATE="07/22/2015 23:59:55" EXPORT_NAME="KERNELBASE.dll" VER_LANGUAGE="Nederlands (Nederland) [0x413]" EXE_WRAPPER="0x0" />
</EXE>
<EXE NAME="kernel32.dll" FILTER="CMI_FILTER_THISFILEONLY">
    <MATCHING_FILE NAME="kernel32.dll" SIZE="1163264" CHECKSUM="0x1FD0A6B3" BIN_FILE_VERSION="6.1.7601.18939" BIN_PRODUCT_VERSION="6.1.7601.18939" PRODUCT_VERSION="6.1.7601.18015" FILE_DESCRIPTION="DLL-bestand voor Windows NT BASE API-client" COMPANY_NAME="Microsoft Corporation" PRODUCT_NAME="Besturingssysteem Microsoft® Windows®" FILE_VERSION="6.1.7601.18015 (win7sp1_gdr.121129-1432)" ORIGINAL_FILENAME="kernel32" INTERNAL_NAME="kernel32" LEGAL_COPYRIGHT="© Microsoft Corporation. Alle rechten voorbehouden." VERDATEHI="0x0" VERDATELO="0x0" VERFILEOS="0x40004" VERFILETYPE="0x2" MODULE_TYPE="WIN32" PE_CHECKSUM="0x12A426" LINKER_VERSION="0x60001" UPTO_BIN_FILE_VERSION="6.1.7601.18939" UPTO_BIN_PRODUCT_VERSION="6.1.7601.18939" LINK_DATE="07/22/2015 23:59:54" UPTO_LINK_DATE="07/22/2015 23:59:54" EXPORT_NAME="KERNEL32.dll" VER_LANGUAGE="Nederlands (Nederland) [0x413]" EXE_WRAPPER="0x0" />
</EXE>
</DATABASE>

Я сделал следующее, чтобы избежать ошибки:

  • Я только прочитал файл Excel и сделал фактический файл Excel доступным только для чтения.
  • Я закрываю все свои соединения сразу после заполнения своих наборов данных или использования моих читателей.
  • Приложение WinForms без OleDB, распространяемое посредством публикации>щелчка один раз, работает для нескольких пользователей одновременно.
  • Если я начинаю новый проект, скопируйте/вставьте весь мой код (так что он точно такой же, но имя приложения другое): два экземпляра моей программы могут быть запущены одновременно...

Это мой первый опыт работы с C#, поэтому будьте осторожны ;-)


person dreojs16    schedule 23.09.2015    source источник
comment
По файлам довольно сложно сказать, в чем может быть ошибка. Как насчет того, чтобы попытаться сделать копию файла Excel, который вы читаете, когда вам это нужно. Таким образом, вместо того, чтобы каждый пользователь обращался к одному и тому же файлу, просто создайте временную копию, и таким образом каждый пользователь технически читает свой собственный файл. Дайте мне знать, если вам нужна помощь с этим маршрутом   -  person TheDanMan    schedule 23.09.2015
comment
@TheDanMan: Наверное, это очень хорошая идея! Я нашел следующий код для его создания. Это правильно? 'code'string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + .xlsx;'code' И нужно ли мне использовать строку fileName в строке подключения для OleDB?   -  person dreojs16    schedule 23.09.2015
comment
Да что-то подобное может сработать. Итак, пользователь читает этот файл   -  person TheDanMan    schedule 25.09.2015
comment
Но где мне указать путь к моему существующему файлу, из которого я хочу создать временный файл (копию)?   -  person dreojs16    schedule 25.09.2015
comment
Это зависит от того, как развернуто ваше программное обеспечение. Я бы посоветовал вам поместить основной файл на сетевой диск, если один файл используется на нескольких машинах. Затем, когда вашему приложению понадобится файл, оно может скопировать его с сетевого диска в папку приложения Application.StartupPath(), а затем использовать его, оставив основной файл нетронутым. Таким же образом, если что-то пойдет не так или файл выйдет из строя, пока пользователь работает с ним, вы будете знать, что это всего лишь временный файл, а не основной файл. Смотрите ответ ниже   -  person TheDanMan    schedule 25.09.2015
comment
Каждый программист .NET со временем обнаруживает, что написание обработчика событий для события AppDomain.CurrentDomain.UnhandledException не является обязательным. Потому что если вы этого не сделаете, то вы понятия не имеете, почему ваша программа не работает, когда она покидает вашу машину разработки.   -  person Hans Passant    schedule 25.09.2015
comment
Вы пытались подключиться/отключиться от БД для каждой операции? Если вы сохраняете открытое соединение для каждого сеанса, блокировка файла является нормальным явлением.   -  person i486    schedule 28.09.2015
comment
@HansPassant, я понятия не имею, о чем вы говорите, возможно, потому, что я не настоящий программист .Net. Если вы действительно считаете, что это важно, пожалуйста, уточните. @TheDanMan, Материнский файл находится на сетевом диске. Теперь я копирую в локальную временную папку пользователя, чтобы я мог перезаписывать ее при каждом запуске программы (чтобы база данных обновлялась с помощью материнского файла). Спасибо за указание в правильном направлении! @ i486, я пробовал, но каждый щелчок в моей программе меняет необходимый набор данных, поэтому с одним пользователем выполняется много подключений. Большой шанс, что другой пользователь захочет подключиться.   -  person dreojs16    schedule 28.09.2015
comment
Посмотрите мой отредактированный ответ ниже и дайте мне знать, поможет ли код   -  person TheDanMan    schedule 29.09.2015


Ответы (2)


Я думаю, проблема в том, что когда вы открываете файл excel, он создает «замок». Обычно, если вы делаете это через интерфейс MS Excel, он выводит предупреждение, и вы можете выбрать, что делать см. здесь. Но в этом случае, поскольку вы читаете его из программы на C#, он может возвращать эту странную ошибку

Я предлагаю вам попробовать сохранить основной файл на сетевом диске и сделать его локальную копию в папке приложения, чтобы каждый пользователь мог использовать свой собственный файл, а не читать один и тот же файл сразу. Сведения о копировании файлов см. здесь

Попробуйте следующий код

string filename = "Streetlife Product Database.xlsx";
string fullfilename = String.Format(@"//MILKYWAY/SO_Arc/template/{1}", Application.StartupPath, filename);
string tempath = System.IO.Path.GetTempPath();
string filenameTemp = String.Format("{0}.xlsx", System.IO.Path.GetTempFileName());
System.IO.File.Copy(fullfilename, filenameTemp, true);
string connetionString = String.Format(@"Provider = Microsoft.ACE.OLEDB.12.0; Data Source ={0};Extended Properties = ""Excel 12.0 Xml;HDR=YES;IMEX=1""", filenameTemp);

using (OleDbConnection oledb = new OleDbConnection(connetionString))
{
    try
    {
        oledb.Open();
    }
    catch (Exception ex)
    {
        oledb.Close();
        oledb.Dispose();

        MessageBox.Show("Error trying to read file: " + ex.Message);                    
    }
 }
person TheDanMan    schedule 25.09.2015
comment
Спасибо за помощь @TheDanMan! Теперь я воссоздал свою базу данных Excel в таблицу SQL-сервера и использую ее как таковую в своей winform. Это прекрасно работает, и я могу запускать столько экземпляров моей формы и читать базу данных, сколько захочу... - person dreojs16; 19.01.2016

Кажется, что у вас может быть только одно подключение OleDB к определенному файлу. Поэтому, когда один пользователь подключается к файлу, другой не может.

К сожалению, драйвер OleDB по умолчанию будет открывать файл исключительно, тогда вы не сможете открыть его, когда он используется кем-то другим, даже просто для чтения.

Взято из Чтение файла Excel с помощью OleDB c#, когда он используется другим процессом

Итак, теперь я копирую (материнский) файл excel во временное место на компьютере пользователя и подключаюсь к временному (дочернему) файлу там. Кажется, это работает, но я пока не могу бросить правильный код.

У меня пока так:

 string filename = @"//MILKYWAY/SO_Arc/template/Streetlife Product Database.xlsx";
            string filenameTemp = System.IO.Path.GetTempFileName();
            System.IO.File.Copy(filename, filenameTemp, true);
            string connetionString = @"Provider = Microsoft.ACE.OLEDB.12.0; Data Source =" + filenameTemp + ";Extended Properties = 'Excel 12.0 Xml;HDR=YES;IMEX=1'";
person dreojs16    schedule 28.09.2015
comment
Вы должны добавить это как комментарий вместо ответа, чтобы избежать путаницы. Я отредактировал ваш фрагмент кода и заставил его работать для нескольких пользователей и нескольких компьютеров. Пожалуйста, смотрите мой ответ. Отметьте это как ответ, если это работает. - person TheDanMan; 28.09.2015