Ошибка вызова из C# приложения метода из C++ CLR DLL
От: SergDegun Россия  
Дата: 18.10.16 20:01
Оценка:
Разработка ведётся в Windows 10 Prof 32bit в Visual Studio 2013.
Есть тестовое WPF C# приложение, в котором на форме расположена всего одна кнопка. В решении в качестве подпроекта с именем TokenApi имеется С++ CLR DLL с одним методом Test(). В WPF приложении ссылка на С++ CLR DLL добавлена в Reference. При нажатии на кнопку в WPF приложении вызывается тестовый метод из DLL.
В свойствах WPF C# приложения на вкладке "Build" в поле "Platform target" установлено значение "x86".
В "Configuration Manager" в "Active solution platform" и у DLL стоит "Win32". У WPF приложения стоит "x86".
При этом на 32 разрядной платформе всё работает, а на 64 разрядной возникает ошибка. Причём ошибка возникает на этапе создания класса, определённого в DLL, т. е. на строчке TokenApi.TokenApi tokenApi = new TokenApi.TokenApi() и не перехватывается блоком catch. В чём здесь дело?
Я проверяю следующим образом: запускаю программу из директории на 32 разрядной платформе. Все работает. Затем эту же директорию копирую на компьютер с 64 разрядной платформой. Удалённо захожу на тот компьютер куда скопировал и запускаю там — не работает. Почему не понятно. Как тогда делать 32 разрядные приложения с C++ CLR DLL, чтобы они работали и на 64 разрядных платформах?

Вот сообщение об ошибке в Event Viewer:
Application: WpfApplication5.exe
 Framework Version: v4.0.30319
 Description: The process was terminated due to an unhandled exception.
 Exception Info: System.IO.FileNotFoundException
 Stack:
 at WpfApplication5.MainWindow.Button_Click(System.Object, System.Windows.RoutedEventArgs)
 at System.Windows.RoutedEventHandlerInfo.InvokeHandler(System.Object, System.Windows.RoutedEventArgs)
 at System.Windows.EventRoute.InvokeHandlersImpl(System.Object, System.Windows.RoutedEventArgs, Boolean)
 at System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject, System.Windows.RoutedEventArgs)
 at System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs)
 at System.Windows.Controls.Primitives.ButtonBase.OnClick()
 at System.Windows.Controls.Button.OnClick()
 at System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs)
 at System.Windows.UIElement.OnMouseLeftButtonUpThunk(System.Object, System.Windows.Input.MouseButtonEventArgs)
 at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate, System.Object)
 at System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate, System.Object)
 at System.Windows.RoutedEventHandlerInfo.InvokeHandler(System.Object, System.Windows.RoutedEventArgs)
 at System.Windows.EventRoute.InvokeHandlersImpl(System.Object, System.Windows.RoutedEventArgs, Boolean)
 at System.Windows.UIElement.ReRaiseEventAs(System.Windows.DependencyObject, System.Windows.RoutedEventArgs, System.Windows.RoutedEvent)
 at System.Windows.UIElement.OnMouseUpThunk(System.Object, System.Windows.Input.MouseButtonEventArgs)
 at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(System.Delegate, System.Object)
 at System.Windows.RoutedEventArgs.InvokeHandler(System.Delegate, System.Object)
 at System.Windows.RoutedEventHandlerInfo.InvokeHandler(System.Object, System.Windows.RoutedEventArgs)
 at System.Windows.EventRoute.InvokeHandlersImpl(System.Object, System.Windows.RoutedEventArgs, Boolean)
 at System.Windows.UIElement.RaiseEventImpl(System.Windows.DependencyObject, System.Windows.RoutedEventArgs)
 at System.Windows.UIElement.RaiseTrustedEvent(System.Windows.RoutedEventArgs)
 at System.Windows.UIElement.RaiseEvent(System.Windows.RoutedEventArgs, Boolean)
 at System.Windows.Input.InputManager.ProcessStagingArea()
 at System.Windows.Input.InputManager.ProcessInput(System.Windows.Input.InputEventArgs)
 at System.Windows.Input.InputProviderSite.ReportInput(System.Windows.Input.InputReport)
 at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr, System.Windows.Input.InputMode, Int32, System.Windows.Input.RawMouseActions, Int32, Int32, Int32)
 at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr, MS.Internal.Interop.WindowMessage, IntPtr, IntPtr, Boolean ByRef)
 at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
 at MS.Win32.HwndWrapper.WndProc(IntPtr, Int32, IntPtr, IntPtr, Boolean ByRef)
 at MS.Win32.HwndSubclass.DispatcherCallbackOperation(System.Object)
 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate, System.Object, Int32)
 at MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(System.Object, System.Delegate, System.Object, Int32, System.Delegate)
 at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority, System.TimeSpan, System.Delegate, System.Object, Int32)
 at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr, Int32, IntPtr, IntPtr)
 at MS.Win32.UnsafeNativeMethods.DispatchMessage(System.Windows.Interop.MSG ByRef)
 at System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame)
 at System.Windows.Threading.Dispatcher.PushFrame(System.Windows.Threading.DispatcherFrame)
 at System.Windows.Threading.Dispatcher.Run()
 at System.Windows.Application.RunDispatcher(System.Object)
 at System.Windows.Application.RunInternal(System.Windows.Window)
 at System.Windows.Application.Run(System.Windows.Window)
 at System.Windows.Application.Run()
 at WpfApplication5.App.Main()

Вот обработчик кнопки в WPF приложении:
    private void Button_Click(object sender, RoutedEventArgs e)
    {
      try
      {
        TokenApi.TokenApi tokenApi = new TokenApi.TokenApi(); //Здесь падает
        tokenApi.Test();
        MessageBox.Show("Проверка завершилась успехом!");
      }
      catch (Exception ex)
      {
        MessageBox.Show(ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
      }
    }

Вот класс в C++ CLR DLL:
// TokenApi.h
#pragma once

using namespace System;

namespace TokenApi {

  public ref class TokenApi
  {
    public: TokenApi()
    {
    }

    public: int Test()
    {
      return 1;
    }
  };
}
Re: Ошибка вызова из C# приложения метода из C++ CLR DLL
От: Lexey Россия  
Дата: 19.10.16 09:51
Оценка:
Здравствуйте, SergDegun, Вы писали:

SD>Я проверяю следующим образом: запускаю программу из директории на 32 разрядной платформе. Все работает. Затем эту же директорию копирую на компьютер с 64 разрядной платформой. Удалённо захожу на тот компьютер куда скопировал и запускаю там — не работает. Почему не понятно. Как тогда делать 32 разрядные приложения с C++ CLR DLL, чтобы они работали и на 64 разрядных платформах?


32-х битные VC++ redistributables ставил на 64-х битный хост?
"Будь достоин победы" (c) 8th Wizard's rule.
Re[2]: Ошибка вызова из C# приложения метода из C++ CLR DLL
От: SergDegun Россия  
Дата: 19.10.16 10:03
Оценка:
Здравствуйте, Lexey, Вы писали:

L>32-х битные VC++ redistributables ставил на 64-х битный хост?


Да, на машине с 64 битной ОС, где проводится проверка, установлены:
Microsoft Visual C++ 2013 Redistributable (x64) — 12.0.30501
Microsoft Visual C++ 2013 Redistributable (x86) — 12.0.30501

Похоже на то, что в системе действительно чего-то не хватает. Нашёл 64 разрядную машину, где всё работает нормально. Как узнать что нужно доставить в системе?
Re[3]: Ошибка вызова из C# приложения метода из C++ CLR DLL
От: alexander_r  
Дата: 19.10.16 12:06
Оценка:
Здравствуйте, SergDegun, Вы писали:

SD>Здравствуйте, Lexey, Вы писали:


L>>32-х битные VC++ redistributables ставил на 64-х битный хост?


SD>Да, на машине с 64 битной ОС, где проводится проверка, установлены:

SD>Microsoft Visual C++ 2013 Redistributable (x64) — 12.0.30501
SD>Microsoft Visual C++ 2013 Redistributable (x86) — 12.0.30501

SD>Похоже на то, что в системе действительно чего-то не хватает. Нашёл 64 разрядную машину, где всё работает нормально. Как узнать что нужно доставить в системе?


можно посмотреть DependencyWalker-ом
если собирается дебажная версия то нужны дебажные библиотеки msvcp120d.dll, msvcr120d.dll...
Re[3]: Ошибка вызова из C# приложения метода из C++ CLR DLL
От: pilgrim_ Россия  
Дата: 19.10.16 12:08
Оценка: +1
Здравствуйте, SergDegun, Вы писали:

SD>Похоже на то, что в системе действительно чего-то не хватает. Нашёл 64 разрядную машину, где всё работает нормально. Как узнать что нужно доставить в системе?


проверь c++/cli сборку утилитой depends http://www.dependencywalker.com .
Re: Ошибка вызова из C# приложения метода из C++ CLR DLL
От: pilgrim_ Россия  
Дата: 19.10.16 12:27
Оценка:
Здравствуйте, SergDegun, Вы писали:

SD>приложения с C++ CLR DLL, чтобы они работали и на 64 разрядных платформах?


Собирай со статической линковкой crt
Re[3]: Ошибка вызова из C# приложения метода из C++ CLR DLL
От: Vladek Россия Github
Дата: 20.10.16 08:19
Оценка:
Здравствуйте, SergDegun, Вы писали:

SD>Похоже на то, что в системе действительно чего-то не хватает. Нашёл 64 разрядную машину, где всё работает нормально. Как узнать что нужно доставить в системе?


Включи Fusion Log.
Re[4]: Ошибка вызова из C# приложения метода из C++ CLR DLL
От: SergDegun Россия  
Дата: 20.10.16 19:03
Оценка:
Здравствуйте, alexander_r, Вы писали:

_>Здравствуйте, SergDegun, Вы писали:

SD>>Похоже на то, что в системе действительно чего-то не хватает. Нашёл 64 разрядную машину, где всё работает нормально. Как узнать что нужно доставить в системе?

_>можно посмотреть DependencyWalker-ом

_>если собирается дебажная версия то нужны дебажные библиотеки msvcp120d.dll, msvcr120d.dll...

Действительно в этом было дело. Я проверял на debug-версии и у неё была ошибка. У release-версии таких проблем нет.
Спасибо вопрос закрыт.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.