How to implement a Brokered Component: Windows Store App - c#

Using the instructions from here: http://visualstudiogallery.msdn.microsoft.com/527286e4-b06a-4234-adde-d313c9c3c23e
Running Visual Studio 2013 as Admin with Update 2.
I create a C# BWRC project, TestBwrc. In Class.cs I add an int property that returns 1.
I add a new project to the solution, a C++ Brokered Windows ProxyStub called TestBwrc.Ps.
I add a reference to the TestBwrc project, and set project Linker properties to Register Output.
I then build the solution.
I add a new project to the solution, a C# blank windows store app, called TestBwrc.Client. I add a reference to the TestBwrc.Ps project.
Solution builds with no errors or warnings.
In the App.xaml.cs OnLaunched method I add TestBwrc.Class c = new TestBwrc.Class();
Visual Studio complains "Cannot resolve symbol 'Class'"
Solution builds with no errors or warnings.
Running the app throws an exception, TestBwrc.Class is not registered.
What am I missing?
Edit:
Also on TestBwrc.Client I added the Extensions tag to the app manifest with the ClassId of TestBwrc.Class and path Value of "..\Debug\TestBwrc.Ps"

The problem is the path Value of "..\Debug\TestBwrc.Ps" in the ActivateableClassAttribute as mentioned in my edit. Though %ProgramFiles% will be expanded, .. is not, nor is $(SolutionDir). So the for dev the only value that works is C:\dev\TestBwrc\Debug\TestBwrc.Ps
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>clrhost.dll</Path>
<ActivatableClass ActivatableClassId="TestBwrc.Class" ThreadingModel="MTA">
<ActivatableClassAttribute Name="DesktopApplicationPath" Type="string" Value="C:\dev\TestBwrc\Debug\TestBwrc.Ps" />
</ActivatableClass>
</InProcessServer>
</Extension>
</Extensions>

Related

Problems with AppServiceConnection when a third project is the package's entry point

I have a solution consisting of a Windows Application Packaging Project that groups two other projects:
A UWP project, named UwpUI, which is the entry point of the package. It can also be launched by protocol activation.
A .NET framework project, named FrameworkLogic, declared as Fulltrust.
An AppServiceConnection connects the two projects and allows a bi-directional communication between them.
It works using a well known pattern, described in this blog post by Stefan Wick:
Uwp with desktop extension-part 3
The package.appxmanifest (of my app) contains this.
<Extensions>
<desktop:Extension
Category="windows.fullTrustProcess"
Executable="FrameworkLogic\FrameworkLogic.exe">
</desktop:Extension>
<uap:Extension Category="windows.appService">
<uap:AppService Name="BidirectionalCom" />
</uap:Extension>
<uap:Extension Category="windows.protocol" Executable="UwpUI.exe"
EntryPoint="UwpUI.App">
<uap:Protocol Name="protoLaunch" />
</uap:Extension>
The uwp starts the fulltrust process like that:
await FullTrustProcessLauncher.LaunchFullTrustProcessForCurrentAppAsync();
In the entrypoint of the fulltrust .net framework, the connection is made with:
Connection = new AppServiceConnection();
Connection.AppServiceName = "BidirectionalCom";
var familyName = Package.Current.Id.FamilyName;
Connection.PackageFamilyName = familyName;
Connection.RequestReceived += Connection_RequestReceived;
Connection.ServiceClosed += Connection_ServiceClosed;
AppServiceConnectionStatus status = await Connection.OpenAsync();
opening the connection result in a call on the uwp side in the method
OnBackgroundActivated(BackgroundActivatedEventArgs args)
Where a reference to the connection is kept. Everything works.
The new requirement is this : set a console app (or a WPF app) as the package entry point.
If the package is launched without arguments, the new console app launches the uwp project by protocol activation. The bi-directional communication between the UWP and the .NET framework is instantiated and used.
If the app is launched with arguments (in my case, from the jumplist), then only the console app is used.
Adding the new project and setting it as the package entry point results in the following error:
DEP0700: Registration of the app failed. [0x80073CF6] AppxManifest.xml(44,10): error 0x80080204: Cannot register the package because the extension is missing an EntryPoint or StartPage attribute.
The solution on this SO post got me further.
Seems logical : the appservice must be defined under the project that uses it, which is not the package's entrypoint anymore.
My package manifest now include a second app (UwpUI) and looks like this:
<Application Id="App" Executable="$targetnametoken$.exe" EntryPoint="$targetentrypoint$">
<uap:VisualElements DisplayName="Home" Description="Package" BackgroundColor="white" Square44x44Logo="Images\Square44x44Logo.png">
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.protocol" Executable="UwpUI.exe" EntryPoint="UwpUI.App" ><uap:Protocol Name="protoLaunch" />
</uap:Extension>
<desktop:Extension Category="windows.fullTrustProcess" Executable="FrameworkLogic\FrameworkLogic.exe">
</desktop:Extension>
</Extensions>
</Application>
<Application Id="App2" Executable="UwpUI.exe" EntryPoint="UwpUI.App">
<uap:VisualElements AppListEntry="none" DisplayName="Home" Description="Package" BackgroundColor="white" Square44x44Logo="Images\Square44x44Logo.png" Square150x150Logo="Images\Square150x150Logo.png">
<uap:DefaultTile ShortName="-TestApp-" Square71x71Logo="Images\SmallTile.png" Wide310x150Logo="Images\Wide310x150Logo.png" Square310x310Logo="Images\LargeTile.png"/>
<uap:SplashScreen BackgroundColor="white" Image="Images\SplashScreen.png" a:Optional="true"/>
</uap:VisualElements>
<Extensions>
<uap:Extension Category="windows.appService" >
<uap:AppService Name="BidirectionalCom" uap4:SupportsMultipleInstances="false"/>
</uap:Extension>
</Extensions>
</Application>
Doing that works as far as launching the fulltrust project, and establishing the connection, with a call to OnBackgroundActivated(BackgroundActivatedEventArgs args). There, I can succesfuly send a request and get an answer.
But I hit two major problems:
Any (static or instance) field or event instantiated in app.xaml.cs of the UwpUI project is null when it is called from another method, including the reference to the connection.
Prior to the modification, in debug mode at least, I could set breakpoints in both the UWP and the .NET framework project by doing 'detach all', then 'attach to process'. Now When attaching, the .NET framework project is greyed out.
Any idea what I'm missing? Problem 1 is the worse, since it breaks the app, but I need to solve the two.
Thank you.
EDIT : When looking at Task Manager, I see two processes with the same entry point (UwpUI.exe). Indeed, breakpoints show me that the call to the uwp constructor ( App.xaml.cs.App()), is called twice.
That certainly explains problem 1: fields are set in one instance and are of course null in the second instance.
Seems I need to structure my manifest differently, but I have yet to find how.
EDIT: Example project Here

"CreateAssetPack" task failed when building MAUI application for iOS

I am creating a new application on MAUI from scratch. The application is successfully built for Android. But when I try to build for iOS, an error occurs, the reasons for which I can not find:
1>C:\Program Files\dotnet\packs\Microsoft.iOS.Sdk\15.4.414\tools\msbuild\iOS\Xamarin.iOS.Common.targets(580,3): error MSB4044: The "CreateAssetPack" task was not given a value for the required parameter "Source".
1>Done building project "Clicker.Mobile.App.csproj" -- FAILED.
Installed all the latest updates on Macbook as well as Visual Studio (installed on Windows). The issue is reproducible on multiple computers. Most likely I'm missing something in setting up for iOS, but the error message does not give anything more informative.
CreateAssetPack task:
<CreateAssetPack
SessionId="$(BuildSessionId)"
Condition="'$(IsMacEnabled)' == 'true' And '$(EmbedOnDemandResources)' == 'false'"
ToolExe="$(ZipExe)"
ToolPath="$(ZipPath)"
Source="%(_AssetPack.Identity)"
OutputFile="$(IpaPackageDir)OnDemandResources\%(_AssetPack.DirectoryName)"
/>
I assume, judging by the compiler logs, that the _AssetPack.Identity property is empty.
I find the description of this element:
<!-- Look for the *.assetpack folders in the ODR folder -->
<CollectAssetPacks
SessionId="$(BuildSessionId)"
Condition="'$(IsMacEnabled)' == 'true' And Exists('$(_IntermediateODRDir)')"
OnDemandResourcesPath="$(_IntermediateODRDir)"
>
<Output TaskParameter="AssetPacks" ItemName="_AssetPack"/>
</CollectAssetPacks>
<ItemGroup>
<_AssetPack>
<_DirectoryName>$([System.IO.Path]::GetDirectoryName('%(Identity)'))</_DirectoryName>
</_AssetPack>
<_AssetPack>
<DirectoryName>$([System.IO.Path]::GetFileName('%(_AssetPack._DirectoryName)'))</DirectoryName>
</_AssetPack>
<_AssetPack>
<CodesignStampFile>$(DeviceSpecificOutputPath)OnDemandResources-codesign\%(DirectoryName)</CodesignStampFile>
</_AssetPack>
</ItemGroup>
But further it is not clear what needs to be specified in the project in order for this object to be initialized.
Which way to look?

The "GenerateFunctionsExtensionsMetadata" task could not be instantiated

Followed the steps to create a sample Azure function from: https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-your-first-function-visual-studio.
The function runs fine locally (using F5), but when I try to publish it to Azure I get the following exception:
2>The "GenerateFunctionsExtensionsMetadata" task could not be instantiated from "C:\Users\<username>\.nuget\packages\microsoft.azure.webjobs.script.extensionsmetadatagenerator\1.2.1\build\..\tools\net46\Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.dll". Could not load file or assembly 'Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator' or one of its dependencies. The system cannot find the file specified.
2>The "GenerateFunctionsExtensionsMetadata" task has been declared or used incorrectly, or failed during construction. Check the spelling of the task name and the assembly name.
The file "Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator.dll" does exist on the specified location.
The project contains the following NuGet packages:
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.16.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.3" />
<PackageReference Include="Microsoft.Azure.WebJobs.Script.ExtensionsMetadataGenerator" Version="1.2.1" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="3.0.11" />
Visual Studio version: 16.8.5
What can be done to investigate this problem further?
One or all of the below can solve your issue:
Make sure that all the prerequisites are installed in your Visual Studio 2019:
Delete bin and obj folders in your solution and rebuild. Now, deploy your solution.
Create a function app on your Azure portal, and then select the function app in Visual Studio, instead of creating through Visual Studio, for deployment.
Make sure, your configuration in Visual Studio is set to Release.

msbuild ignores passed ReferencePath

Summary:
I'm passing /p:ReferencePath to msbuild, when building a Xamarin.Android project. This does work with Visual Studio 2017, but not with Visual Studio 2019.
In detail:
I have two projects:
Xamarin.Forms (with main class library, iOS and Android project underneath)
Class library
The Xamarin.Forms project is referencing the class library via HintPath directly in Debug build. On the build server (Jenkins) things work differently (release build) and the library is build separately. Therefore I use ReferencePath to overwrite the stored HintPath and reference the class library (dll) on the Jenkins server, which was previously build.
The failing build command looks like this
"C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin\MSBuild"
TestJenkins/TestJenkins/TestJenkins.Android/TestJenkins.Android.csproj
/p:Configuration=Release /p:ReferencePath=C:\Jenkins\workspace\TestMSBuild\MPL1.0
/t:PackageForAndroid /t:Build /v:diag
I left out the other parts, because they do work. When reading the output log I noticed the following, when building with Visual Studio 2019:
the ResolveAssemblyReference task doesn't list the passed ReferencePath under SearchPaths= for the Android build, but it is listed for the class library build (the main library for the Xamarin.Forms project and not the separate class library)
one warning MSB3245
multiple error CS0246
On another Jenkins machine there is Visual Studio 2017 installed and the same code, the same scripts does work without an error. So the question is, what's the difference. Lately, I upgraded to .NET Standard. Perhaps I forgot something?
What I've tried:
set up a similar test project, but here it fails with error CS0103
use hard coded link to the dll with BeforeResolveReferences and this does work, but that is only a hack (continous integration should not work that way)
adding ReferencePath in csproj in Android project, but still the same errors
changed Copy local in the Android project
Visual Studio 2019 does build the project on the Jenkins server, if I update the references and use hard-coded links
read the diagnostic log (140k lines)
read the manual, but the use of RerencePath is not really explained
many more ...
Question:
As you can see I'm using the build tools of Visual Studio 2019, but I don't know what has changed to Visual Studio 2017 Build Tools. Am I calling msbuild wrong? Does /p:ReferencePath works different than I expect? Can someone give me a hint to find the cause for this?
Edit (1):
Now I found the following out: The CS0246 error point to lines in my Android project, where a using statement is made: e.g. using MyClassLibrary.Component.Feature;.
The MSB3245 warning seams to occur if the HintPath in the Android project can't be resolved.
Back to the using statement: I have an interface defined my external class library. A class in the Android project implements this. E.g.
Code in external class library:
public interface ITextService
{
string GetText();
}
Code in Android project:
using SomeLibrary; // error CS0246
using Xamarin.Forms;
[assembly: Dependency(typeof(TestJenkins.Droid.TextService))]
namespace TestJenkins.Droid
{
public class TextService : ITextService // error CS0246
{
public string GetText()
{
return SomeLibrary.ServiceClass.NativeKey;
}
}
}
The question still is, why can't the reference from the Android project be resolved?
Edit (2):
For me that must be a bug in msbuild with VS2019 or a behavior change. So I thought I can combine this with this:
<Project DefaultTargets="Build" InitialTargets="ValidateToolsDllExists" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="ValidateToolsDllExists">
<Error
Text=" The ToolsDllPath property must be set on the command line."
Condition="'$(ToolsDllPath)' == ''" />
<Error
Text=" The ToolsDllPath property must be set to the full path to tools.dll."
Condition="!Exists('$(ToolsDllPath)')" />
</Target>
<Target Name="BeforeResolveReferences">
<CreateProperty
Value="$(ToolsDllPath);$(AssemblySearchPaths)">
<Output TaskParameter="Value"
PropertyName="AssemblySearchPaths" />
</CreateProperty>
</Target>
<!-- ... -->
</Project>
But passing /p:ToolsDllPath=C:\path\to\my\dll to msbuild still throws the CS0246 error.

TypeLoadException using WinRT Brokered Component

I am building a Windows Store App using a brokered component. The brokered component is meant to enable interaction with an RFID reader on the device. When I try to initialize an instance of the class exposed by the brokered component, I received a System.TypeLoadException with the message Could not find or load a type. (Exception from HRESULT: 0x80131522).
I'm working against a clean installation of Windows 8.1 Professional on two different tablet devices. Both are currently experiencing this issue. The solution has worked in the past; something I've done recently must be causing this. I've also verified that the RFID reader can be accessed using a sample application provided by the hardware vendor.
My Package.appxmanifest file looks similar to this:
<Package ...>
...
<Extensions>
<Extension Category="windows.activatableClass.inProcessServer">
<InProcessServer>
<Path>clrhost.dll</Path>
<ActivatableClass ActivatableClassId="MyApp.RFID.Component.RfidDevice" ThreadingModel="STA">
<ActivatableClassAttribute Name="DesktopApplicationPath" Type="string" Value="C:\Program Files (x86)\MyApp\RFID" />
</ActivatableClass>
</InProcessServer>
</Extension>
</Extensions>
</Package>
The solution is being built to target an x86 platform. I've registered my components on the target device under C:\Program Files (x86)\MyApp\RFID using the following commands (per this whitepaper):
icacls . /T /grant "ALL APPLICATION PACKAGES":RX
regsvr32 MyApp.RFID.Proxy.dll
I've installed the Visual Studio 2013 x86 Redistributable Package on the target device. I've also placed an additional dependency .dll in the same directory, just as I have been doing during all of my development.
Some other things I've tried:
Using %PROGRAMFILES% instead of C:\Program Files (x86) as the value for the ActivatableClassAttribute in the manifest.
Using 'STA', 'MTA', and 'Both' as the threading models.
Added a trailing slash to the ActivatableClassAttribute value path.
Completely uninstalled everything and tried again from scratch.
Explicitly add an empty default constructor to the RfidDevice class.

Categories