Проблемы при запуске отчета с машины, на которой не установлен Fastrepor.net
При запуске отчета с машины, на которой не установлен FastReport.NET, возникает исключение "System.IO.FileNotFoundException: Невозможно загрузить файл или сборку \"FastReport, Version=1.4.12.0, Culture=neutral, PublicKeyToken=db7e5ce63278458c\" или один из зависимых от них компонентов. Не удается найти указанный файл.":"FastReport, Version=1.4.12.0, Culture=neutral, PublicKeyToken=db7e5ce63278458c"
Трассировка:
в System.Signature._GetSignature(SignatureStruct& signature, Void* pCorSig, Int32 cCorSig, IntPtr fieldHandle, IntPtr methodHandle, IntPtr declaringTypeHandle)
в System.Signature.GetSignature(SignatureStruct& signature, Void* pCorSig, Int32 cCorSig, RuntimeFieldHandle fieldHandle, RuntimeMethodHandle methodHandle, RuntimeTypeHandle declaringTypeHandle)
в System.Signature..ctor(RuntimeFieldHandle fieldHandle, RuntimeTypeHandle declaringTypeHandle)
в System.Reflection.RtFieldInfo.get_FieldType()
в System.Reflection.RtFieldInfo.GetOneTimeFlags()
в System.Reflection.RtFieldInfo.InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, Boolean doVisibilityCheck, Boolean doCheckConsistency)
в System.Reflection.RtFieldInfo.InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, Boolean doVisibilityCheck)
в System.Reflection.RtFieldInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.YSJAbu2C3(String , Object )
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.Ef38gNOqM()
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.BemEBWqd2(Object )
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.B0Dfqkgea()
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.0KvIVgbeU()
в FastReport.Report.tOZtoxwPY()
в FastReport.Report.Prepare(Boolean append)
в FastReport.Report.Show(Boolean modal, Form owner)
в FastReport.Report.Show()
в Person.Scan.PhotoEditor._PrintBadge(Int32[] tabNumbers)"
Код, вызывающий отчет: (отчет размещается в файле ресурсов, данные регистрируются в коде, сгенерированом дизайнером VS).
try {
this.report1.Show();
} catch(Exception ex) {
string _msg=string.Empty;
for(Exception _ex=ex;_ex!=null;_ex=ex.InnerException) {
_msg+=string.Format("{0}: {1}\n",_ex.GetType().FullName,_ex.Message);
}
MessageBox.Show(_msg,"Person.Scan.dll",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
В результате анализа удалось выявить участок кода (в FastReport.dll), приводящий к ошибке:
файл AssemblyDescriptor.cs, строка 62:
58: private void InitField(string name, object c)
59: {
60: FieldInfo info = Instance.GetType().GetField(name,
61: BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
62: info.SetValue(Instance, c);
63: }
метод SetValue(...) приводит к исключению, в случае, если отчет скомпилирован в память. Если его скомпилировать в файл, то все работает нормально.
Проблема в том, что в коде, компилирующем отчет, жестко протисано, что компилировать нужно в память (файл AssemblyDescriptor.cs, строка 349):
344: using (CodeDomProvider provider = Report.CodeHelper.GetCodeProvider())
345: {
346: CompilerParameters cp = new CompilerParameters();
347: AddFastReportAssemblies(cp.ReferencedAssemblies);
348: AddReferencedAssemblies(cp.ReferencedAssemblies);
349: cp.GenerateInMemory = true;
350: // sometimes the system temp folder is not accessible...
351: if (Config.TempFolder != null)
352: cp.TempFiles = new TempFileCollection(Config.TempFolder, false);
353: CompilerResults cr = provider.CompileAssemblyFromSource(cp, FScriptText.ToString());
Конечно можно работать с отчетом, сохраненным ввиде класса, но это не решение проблемы.
Возможно ли исправить эту ситуацию?
В дополнение: приложение, вызывающее отчет, иначально unmanaged, затем загружается managed код, который, собственно, и вызывает отчет
Трассировка:
в System.Signature._GetSignature(SignatureStruct& signature, Void* pCorSig, Int32 cCorSig, IntPtr fieldHandle, IntPtr methodHandle, IntPtr declaringTypeHandle)
в System.Signature.GetSignature(SignatureStruct& signature, Void* pCorSig, Int32 cCorSig, RuntimeFieldHandle fieldHandle, RuntimeMethodHandle methodHandle, RuntimeTypeHandle declaringTypeHandle)
в System.Signature..ctor(RuntimeFieldHandle fieldHandle, RuntimeTypeHandle declaringTypeHandle)
в System.Reflection.RtFieldInfo.get_FieldType()
в System.Reflection.RtFieldInfo.GetOneTimeFlags()
в System.Reflection.RtFieldInfo.InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, Boolean doVisibilityCheck, Boolean doCheckConsistency)
в System.Reflection.RtFieldInfo.InternalSetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture, Boolean doVisibilityCheck)
в System.Reflection.RtFieldInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, CultureInfo culture)
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.YSJAbu2C3(String , Object )
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.Ef38gNOqM()
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.BemEBWqd2(Object )
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.B0Dfqkgea()
в qenkKr3sLuA2VuH2x8.9oeHvTQ1k9dVJNvTH7.0KvIVgbeU()
в FastReport.Report.tOZtoxwPY()
в FastReport.Report.Prepare(Boolean append)
в FastReport.Report.Show(Boolean modal, Form owner)
в FastReport.Report.Show()
в Person.Scan.PhotoEditor._PrintBadge(Int32[] tabNumbers)"
Код, вызывающий отчет: (отчет размещается в файле ресурсов, данные регистрируются в коде, сгенерированом дизайнером VS).
try {
this.report1.Show();
} catch(Exception ex) {
string _msg=string.Empty;
for(Exception _ex=ex;_ex!=null;_ex=ex.InnerException) {
_msg+=string.Format("{0}: {1}\n",_ex.GetType().FullName,_ex.Message);
}
MessageBox.Show(_msg,"Person.Scan.dll",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
В результате анализа удалось выявить участок кода (в FastReport.dll), приводящий к ошибке:
файл AssemblyDescriptor.cs, строка 62:
58: private void InitField(string name, object c)
59: {
60: FieldInfo info = Instance.GetType().GetField(name,
61: BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
62: info.SetValue(Instance, c);
63: }
метод SetValue(...) приводит к исключению, в случае, если отчет скомпилирован в память. Если его скомпилировать в файл, то все работает нормально.
Проблема в том, что в коде, компилирующем отчет, жестко протисано, что компилировать нужно в память (файл AssemblyDescriptor.cs, строка 349):
344: using (CodeDomProvider provider = Report.CodeHelper.GetCodeProvider())
345: {
346: CompilerParameters cp = new CompilerParameters();
347: AddFastReportAssemblies(cp.ReferencedAssemblies);
348: AddReferencedAssemblies(cp.ReferencedAssemblies);
349: cp.GenerateInMemory = true;
350: // sometimes the system temp folder is not accessible...
351: if (Config.TempFolder != null)
352: cp.TempFiles = new TempFileCollection(Config.TempFolder, false);
353: CompilerResults cr = provider.CompileAssemblyFromSource(cp, FScriptText.ToString());
Конечно можно работать с отчетом, сохраненным ввиде класса, но это не решение проблемы.
Возможно ли исправить эту ситуацию?
В дополнение: приложение, вызывающее отчет, иначально unmanaged, затем загружается managed код, который, собственно, и вызывает отчет
Комментарии
А разработчики видимо ушли "за дальний кордон..." .
Для начала попробуйте обновить версию до текущей 1.4.46.
Может проблема уже решена.
Конечно интересная версия, но темнеменее файлы FastReport.dll, FastReport.Bars.dll копируются вместе с приложением.
1. Попробуйте удалить ссылки на сборки, и добавить их заново.
И еще. Вопрос. Какие версии .NET Framework на компьютере где работает и где нет?
Обновление ссылок результат не меняет. На ПК установлены Framework версий 2.0, 3.0, 3.5 и 4.0.
Скажу сразу, от версий framework это не зависит. Мне кажется разница в том, где находятся сборки Fast Report: в GAC или не в GAC. В случае, если Fast Report установлен, соответствующие сборки находятся в GAC и тогда ошибки не возникает; иначе возникает
1. Вы добавляете в проект ссылки на сборки установленные в GAC. В этом случае на компьютере пользователя эти сборки тоже должны быть установлены в GAC. Простого копирования dll-файлов сборок со своим приложением не достаточно.
2. Вы добавляете в проект сборки не установленные в GAC. В этом случае компилятор, при создании exe-файла, в папку с ним копирует dll-файлы сборок. Их нужно скопировать на компьютер пользователя в папку с исполняемым файлом.
У вас есть какие-нибудь причины по которым вы не можете установить сборки в GAC на компьютере пользователя?
Естественно есть: требуемое приложение запускается с локального сетевого ресурса, и оно должно работать без каких-либо предварительных установок, т.к. пользователей приложения моного и они распределены по всей територии предприятия (весьма крупного) (ко всем не дойдешь). Если реализовывать механизм инсталяции just-in-time (т.е. по мере необходимости), то в случае с GAC необходимо иметь полномочия администратора для установки туда сборок, а это недопустимо для пользователей предприятия (из соображений безопасности).
Нашли ли Вы решение вашего вопроса? Подскажите, пожалуйста, что Вы сделали, чтобы решить эту проблему.
Решение нашлось.
Потребовалось создать собственный механизм компиляции отчета, с сохранением полученой сборки во временных файлах.