Xamarin.Forms App crashes on iOS when installed via Testlfight - c#

Hello fellow developers!
I am developing a Xamarin.Forms App for android and iOS.
It works fine in Debug and Release mode on Android Emulators, Android Devices, iOS Emulators.
But there is a problem with iOS Devices. Directly deploying the Debug/Release Builds to a device works. But when I upload the app to the AppStore and install it via Testflight on my device, it crashes on startup.
From the console I can see following errors:
"System.MissingMethodException: Default constructor not found for type App.Views.Login"
"Default constructor not found for type ColorPicker.iOS.Effects.ColorPickerTouchEffectiOS"
The first one is related to my Login View, which has a default constructor and works fine in debug and release builds.
The second one is related to a nugget package.
My question is:
Why are the default constructors available in Debug and Release but not when i download the app via Testflight? And how can I fix this?
Linking behaviour is set to "Link all".

That's because when you use the Link all assemblies option you need to manually preserve the classes in your project and potentially mark out library code that isn't linker safe.
There is a Microsoft document specifically catering to this question : https://learn.microsoft.com/en-us/xamarin/ios/deploy-test/linker?tabs=macos
You could set your linker behaviour to Link SDK assemblies only temporarily while you manually get ready for a full link.
Preservin code:
When you use the linker it can sometimes remove code that you might have called dynamically either using System.Reflection.MemberInfo.Invoke, or by exporting your methods to Objective-C using the [Export] attribute and then invoking the selector manually.
In those cases, you can instruct the linker to consider either entire classes to be used or individual members to be preserved by applying the [Xamarin.iOS.Foundation.Preserve] attribute either at the class-level or the member-level. Every member that is not statically linked by the application is subject to be removed. This attribute is hence used to mark members that are not statically referenced, but that are still needed by your application.
Skipping Assemblies
It is possible to specify assemblies that should be excluded from the linker process, while allowing other assemblies to be linked normally. This is helpful if using [Preserve] on some assemblies is impossible (e.g. 3rd party code) or as a temporary workaround for a bug.
--linkskip=NameOfAssemblyToSkipWithoutFileExtension // Single assembly
--linkskip=NameOfFirstAssembly --linkskip=NameOfSecondAssembly // Multiple Assemblies
Hope this helps. Make sure you go through the MS doc for more details

Related

C# Dynamic compile and replace/reload of assembly from within same assembly

I have several issues with several SDK's comming from OEM manufacturers for specific devices. SDK is usually based on C or C++ dll, so I have a lot of Marshaling going around (a lot===YOU CAN'T EVEN IMAGINE). Problem start with next version of SDK when they extend some functions or some structures, they effectively break compatibility. In past I have made copy of our library supporting their device and start making changes to support new SDK. But each time our library was only for specific SDK, and upgrades of our systems were tough (Installation script if one heavy thing also ~ 3 GB install).
I have 78 projects in solution, commonly 4-5 libraries for each OEM Manufacturer, this is without any service tools. And Yesterday I said NO MORE. Started research on subject how to recompile C# code in runtime and reload/replace same assembly without quiting App.
And the result is the following:
- Class file that defines external C/C++ dll API was referenced from external Project referencing only System.dll. And me being insane I've already had each SDK version changes wrapped around #if #elif #endif so I could recompile last version of our library to support previous version of SDK. But that was maybe only once done, I've used #defines along with CSharpCodeProvider to recompile this assembly in runtime. Idea was like this:
Application loading ...
Open main SDK file get file version (extract version and identify it).
Load original External Assembly in new AppDomain (so I could destroy domain later).
Extract current version from external assembly.
Destroy new AppDomain to release hook from external assembly.
If versions mismatch, recompile external assembly (source code for external assembly is embedded within parent assembly), and replace original DLL with just compiled one.
Continue loading application...
So far this test approach works on one live demo system, and I was amazed. Switching from one to another SDK was flawless without any hick-ups.
And also code recompiles it self only when SDK version changes. So with safe guard I could say this is my first Metamorphic code I've wrote, that recompiles/changes it self from runtime.
Unfortunately this approach requires me to add one more Project for each OEM Manufacturers SDK. Which effectively kills my first though why I said NO MORE. True I now have only two libraries to maintain per one OEM manufacturer, and there will be no more projects added after this. But...
I wonder is there better approach which could allow me to replace DLL of currently loaded assembly in runtime from true within same assembly? Or change executing code on "fly" each time, this mainly includes Marshaled function, classes, structures, constants, ...?
Please notice code should be maintained from within same project without any externals. Also please notice this project exposes only hard-coded interface to "outside" world (Interface is referenced Interface only project - is more complex than I wrote). But this "outside" world is blind to any OEM specific stuff, which was the point using interface to have exactly same behavior across any OEM Device.
Any ideas? thoughts? suggestions?

Creating Wp8 Unity Plugin in Unity 5.0

I have a windows phone 8.0 plugin created for an app. This app worked perfectly fine in Unity 4.5. I recently updated my Unity to 5.0. I also saw all the needed alterations.
Initially, we needed to create two plugin dlls. One actual and one empty simply like an interface for the editor. This went pretty well in unity 4.5
Now i open the same app in Unity 5.0 by upgrading it. and i am unable to build it for wp8 anymore. I set the inspector platforms correctly to WP8 player for my plugin dll.
But, i keep getting errors like ::
1. Plugins are colliding.
2. There are errors in the script (which are actually not)
3. Cannot load classes from module.
4.System.Reflection.ReflectionTypeLoadException: The classes in the module cannot be loaded.
etc.
Can anybody help me? I have tried several things already but none seems to work.
I tried :
1. Reimporting everything
2. Rebuilding the dlls.
3. Removing the empty interfaced dll for editor
4. Changing the folder structure for plugins. (Default being
Assets/Plugins/WP8)
I am stuck here since two days now.
Well, it's too late to reply. But anybody else stuck in same problem may get help.
One should know that WP8 Plugins are based on real and fake dlls in order to work in Unity Editor.
In Unity 5, you can specify platform to dll, irrespective of folder structures. However if you put dll in Assets->Plugins->WP8. Unity will mark it as WP8 dll.
Solution is,
1- Put Fake dll in Assets->Plugins->AnyFolder->plugin.dll, where any AnyFolder is other than WP8 folder. Mark it as Editor instead of Any Platform (from inspector [Select platform for plugins]).
2- Put Original dll in Assets->Plugins->WP8->plugin.dll, mark it as WP8Player
3- Keeping original dll selected, in Platfrom Settings [Inspector] modify settings like, CPU -> Any CPU, check mark on Don't Process, Select placeholder.
Placeholder drop down would show the path of fake dll, just set it.
Now you are all done :)
You must set the editor DLLs to "Editor" instead of "Any Platform" and the WP8 plugins to "WP8Player" in the plugin settings.

WPF Application Incorporating WinAPI (Win8) components

I have a WPF application which utilizes a handwriting control.
By using an
<InkCanvas></InkCanvas>
In my XAML, I was able to get the user's strokes, and turn them into text using the InkAnalysis class. However, this is strictly 32bit, and my requirements dictate a 64bit build.
Unable to find a 64bit compatible library, I looked into upgrading to .NET 4.5 and utilizing the Windows8 classes which are available to desktop apps (by also adding
<TargetPlatformVersion>8.1</TargetPlatformVersion> to the csproj file so that I could add the 'Windows' namespace references). Luckily, Windows.UI.Input.Inking is.
However, when I add the reference to Windows.UI.Input.Inking, I get a build error which states:
Unknown build error, 'Cannot resolve dependency to Windows Runtime type 'Windows.Foundation.Metadata.PlatformAttribute'. When using the ReflectionOnly APIs, dependent Windows Runtime assemblies must be resolved on demand through the ReflectionOnlyNamespaceResolve event.'
I have looked into the:
Windows.Foundation.Metadata.PlatformAttribute
And it seems to want an enum member, either:
Windows.Foundation.Metadata.Platform.Windows
or
Windows.Foundation.Metadata.Platform.WindowsPhone
This is a desktop application, so I would obviously choose to target Platform.Windows, but cannot figure out how to tell the compiler this.
How can I incorporate this Windows.UI.Input.Inking class into my WPF application? My end goal is simply to convert strokes from the inkcanvas into text, in a 64 bit environment.
I discovered that I was receiving this error due to the reference added to the:
Windows.UI.Input.Inking
library. It seems that the correct way to add reference to Windows 8/8.1 WinAPI components (from a non WinAPI application) is the following:
Add <TargetPlatformVersion>8.1</TargetPlatformVersion> to the csproj file
Add reference to the Windows library (this is the key - adding the specific lib, in this case, Windows.UI.Input.Inking, causes the build error)
Add the more specific (ex: Windows.UI.Input.Inking) reference in the actual file where the API is required
I am working on creating a NuGet package which will edit the csproj file, and add the Windows reference. I'll update this if/when it is completed.

How can C# use a legacy DLL simply without registration(regsvr32)

Situation
I run a build system that executes many builds for many project. To avoid one build impacting another we lock down the build user to only its workspace. Builds run as a non privileged users who only have write ability to the workspace.
Challenge
During our new build we need to use a legacy 3rdparty DLL that exposes its interface through COM. The dev team wants to register the build(regsrv32.exe) but our build security regime blocks this activity. If we relax the regime then the 3rdparty DLL will impact other builds and if I have two build which need two different versions I may have the wrong build compile against the wrong version (a very real possibility).
Question
Are there any other options besides registration to handle legacy DLLs which expose their interface via COM?
Thanks for the help
Peter
For my original answer to a similar question see: TFS Build server and COM references - does this work?
A good way to compile .NET code that references COM components without the COM components being registered on the build server is to use the COMFileReference reference item in your project/build files instead of COMReference. A COMFileReference item looks like this:
<ItemGroup>
<COMFileReference Include="MyComLibrary.dll">
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMFileReference>
</ItemGroup>
Since Visual Studio provides no designer support for COMFileReference, you must edit the project/build file by hand.
During a build, MSBuild extracts the type library information from the COM DLL and creates an interop assembly that can be either standalone or embedded in the calling .NET assembly.
Each COMFileReference item can also have a WrapperTool attribute but the default seemed to work for me just fine. The EmbedInteropTypes attribute is not documented as being applicable to COMFileReference, but it seems to work as intended.
See https://learn.microsoft.com/en-ca/visualstudio/msbuild/common-msbuild-project-items#comfilereference for a little more detail. This MSBuild item has been available since .NET 3.5.
It's a shame that no-one seems to know anything about this technique, which to me seems simpler than the alternatives. It's actually not surprising since I could only find just the one above reference to it on-line. I myself discovered this technique by digging into MSBuild's Microsoft.Common.targets file.
There's a walkthrough on registration-free COM here:
http://msdn.microsoft.com/en-us/library/ms973913.aspx
And excruciating detail here:
http://msdn.microsoft.com/en-us/library/aa376414
(the root of that document is actually here: http://msdn.microsoft.com/en-us/library/dd408052 )
Also, for building in general, you should be able to use Tlbimp or tlbexp to create a TLB file that you can use for building, assuming the point of registering is just to be able to compile successfully, and not to run specific tests.
Installation tools such as Installshield can extract the COM interfaces from the DLLs and add them to the registry. It can also use the self-registration process of the DLL (which I believe is what regsvr does), but this is not a Microsoft installer best practice.
in .NET COM is normally done thru Interop in order to register .DLL in .NET they are called Assemblies and that can be done several ways.. by adding references via VS IDE at the project level, or writing code that Loads and unloads the assembly.. by .Config file that haas the reference to the assembly as well as the using of that reference within the project... GAC.
If you have access to the 3rd party .DLL's you can GAC them, and reference them in your project
you can add a using to your .cs file header as well as add the reference to the project by right clicking on reference --> add Reference ...
you can also do the above step as well as set the copy local = true in the properties for that .dll.. I hope that this gives you some ideas.. keep in mind that .NET assemblies are Managed code so there are several ways to Consume those 3rd party .DLL's using other methods within C# like LoadFromAssembly ect..
Thanks for all the help.
We changed from early-binding to late-binding because we never really needed the DLL at compile time. This pushed the registration requirement from the build server to the integration test server (where we execute the installer which handles the registration). We try to keep the build system pristine and have easy-to-reset integration systems.
Thanks again
Peter

How to create a generic use library

I have an image editor user control(c# .net v2.0). Its used in thousands of computers as an activex component. I want the component also be available for windows forms and possible other uses.
For activex usage i add <object> tag in html code and call the component with clsid(a static guid). So if i build and distribute a newer version it works without changing any client code.
I want windows forms to be able use the same distributed libraries. And they should not reference a specific version so i can update the component without changing the programs that use it.
I use regasm to register for com. But i dont know how to reference it from visual studio(like referencing with clsid?)
May be in visual stuido when i choose add reference and select COM tab i shuld see my component in the list.
note: i tried to add the assemly to the global cache using these lines but it did not work out-or i coulnt understand if anything has changed :)
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\tlbexp" ImageEditorComp.dll /out:ImageEditorComp.tlb
regasm /tlb:ImageEditorComp.tlb ImageEditorComp.dll
"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\gacutil" /I ImageEditorComp.dll
Any suggestions appreciated,
Regards
This is not possible, you'll invoke the infamous and dreaded DLL Hell problem. A stone cold hard rule in COM is that you have to change the [Guid] attribute values on public interfaces when you make a breaking change in either the publicly visible interfaces or the implementation of them. Changing the guids ensures that you don't overwrite the registry keys of an old version of your component when you use Regasm.exe. Existing programs that use your component and were not recompiled to use the latest version will continue running without problems. The typical outcome of DLL Hell is a nasty hardware exception like AccessViolation, very difficult to troubleshoot.
None of which applies in your specific case here. There is no point in trying to use the component through COM. It is a .NET assembly, just add the reference to it directly. The IDE will in fact stop you from adding a reference to the interop library. But not the .tlb. The GAC keeps you out of DLL Hell, assuming you properly increment [AssemblyVersion].
I figured out a solution.
To explain step by step:
1- Create the component with all needed properties for com.(Sign the assembly, use interfaces for com, make assembly com visible)
On the client machine
2- Register the assembly with regasm(i recommend adding safety flags too).
3- Add the assembly to the global cache using gacutil(or msi installer)
I figured out when you call a specific version of an assembly gac is searched in the first place so if its installed in GAC, referenced codebase path is never used.
When using as activeX you address the component with GUID. Since regasm adds the assembly name and version the GUID is representing, web browser directly uses component from GAC.
When using from a desktop application, reference the assebmly directly and set copylocal property to false. Similarly, in the client machine windows will find the assembly located at GAC itself.
Here is a useful link about the subject.
http://www.simple-talk.com/dotnet/visual-studio/build-and-deploy-a-.net-com-assembly/
Hope it saves other peoples time :)

Categories