Does WP7 background agent have to be in a separate DLL? - windows-phone

Reading up on background agents in Windows Phone. All guides say I should start with creating a new project specifically for the agent. Is that a requirement? Cite place.
The bigger question is - how does the framework find the class that implements the scheduled task? AFAIK, starting a background task involves calling ScheduledActionService.Add() passing a ScheduledAction-derived object as a parameter. Nowhere in here can I see any pointer to the identity of task's implementation. Neither are tasks registered in the manifest.

Yes, the background task needs to be located in separate project. In theory the background task could be in the original project, but then it will easily hit the memory cap, because the whole project needs to be loaded in order to run just the background task code.
It also needs to be added into your main app project using "Add reference".
The project with background task also need to have class, that is a child of ScheduledTaskAgent class.
Then (in case of WP8 app) when your app is built using Visual Studio and if the Visual Studio finds such referenced project with ScheduledTaskAgent, new entry is injected into the WMAppManifest.xml to tell the app launcher that this app has background task available and in case user actually register this task for running, WP OS should start the assembly located in app manifest. This is how it looks in the manifest file:
<Tasks>
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" ActivationPolicy="Resume" />
<ExtendedTask Name="BackgroundTask">
<BackgroundServiceAgent Specifier="ScheduledTaskAgent" Name="EreaderBackgroundAgent" Source="EreaderBackgroundAgent" Type="EreaderBackgroundAgent.ScheduledAgent" />
</ExtendedTask>
</Tasks>
The DefaultTask entry just describes the default app entry point, the ExtendedTask is the entry for background task.
Note also that when developing apps for Windows Phone 7.5, this entry had to be added manually into the manifest and it was a common problem that devs published app without this entry in manifest.
Also another interesting discovery, if you reference in your main project -> libraryA, that is referencing another libraryB, and only the libraryB implements the ScheduledTaskAgent, then Visual Studio won't add the entry into manifest, because it cannot check indirectly referenced projects - if the libraryA has no ScheduledTaskAgent implementation, the library is not considered as background task library. But, you can again add the entry to libraryA into manifest manually and it will work just fine.

Neither are tasks registered in the manifest.
They are. See the "BackgroundServiceAgent" element in your manifest file: http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff769509(v=vs.105).aspx
In the end, I don't know if creating a separate project is a requirement. By manually adding the line in the manifest and pointing to a class in the main project, I don't see what could technically prevent the background agent from working. I haven't tried though. Still, putting the background agent in a separate assembly can be convenient: the memory limit for agents is ridiculously low, so not having to load the main project and its dependencies can probably save a few hundreds KB of memory

Related

What is it called when an app set some configurations at build time?

A common pattern used to build applications/software (web, mobile, desktop) is to have multiple build configs like Dev, Stage and Production. Each one of these configs may overwrite multiple variables like the base url of a web service that is consumed by the application. These configs may be stored in multiple ways (.env file, a JSON config file, etc).
I was looking for a name for this pattern/practice and how to implement it on a VB.NET application. Most close thing I was able to found is using the app.config file to store app settings but this is missing the multiple environments part. I'm having some trouble looking for solutions since I don't know the proper term for this practice.
There's a Solution Configurations drop-down on the main toolbar. You would have already used it to select Debug or Release. You can open the Configuration Manager from there to create new build configurations.
You can then control what happens during the build process of a project for a particular configuration on the Build page of the project properties. You can also perform actions using build events, which you configure on the Build Events page of the project properties. Here's an example of a pre-build event commandline that I use to automatically select the appropriate config file for NLog:
IF EXIST "$(ProjectDir)nlog.$(ConfigurationName).config" XCOPY "$(ProjectDir)nlog.$(ConfigurationName).config" "$(ProjectDir)nlog.config" /Y

ClickOnce app built via Jenkins throwing CS1704 - An assembly with the same simple name {whatever} has already been imported

I have a winforms app, which is deployed via click-once publishing.
Assuming my tests are correct, the only way to have this same app installed more than once in the same machine, is the each publish be made for a different Assembly Name.
My problem is that I am running the msbuild via jenkins, and, to accomplish the above, I would add /p:AssemblyName={whatever}, which will rename all assemblies generated by the build to this same {whatever} value. If the output of my build is 1 exe and 5 dlls, all 6 files will be named {whatever}.
Which in turn raises CS1704: An assembly with the same simple name {whatever} has already been imported.
Is the only way out of this to perform all csc.exe calls that msbuild generates, myself, and see if I can set different assembly names per project ?
Or are there other ways to solve this ?
The problem here is that every property passed to MSBuild as a command line argument is considered a global property and will override the property on all projects built in that invocation. The solution is to introduce an intermediate property that only the "main" project consumes.
Edit the app's csproj file to include this (in the place where AssemblyName is already defined - assuming here that WindowsFormsApp1 is the name of the application):
<AssemblyName>WindowsFormsApp1</AssemblyName>
<AssemblyName Condition="'$(OverrideAssemblyName)' != ''">$(OverrideAssemblyName)</AssemblyName>
you can then use the msbuild commands using /p:OverrideAssemblyName=AnotherName without creating conflicting assembly names on referenced libraries. The property is still defined globally, but only one project consumes it.

How to start assembly from GAC?

I try to do the following:
Put a complete program to gac and start it from there.
I tried:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\ngen install C:\GacTest\test.exe
The output said a lot with compiling assemblies which looked good - references classes should be bundled with application.
But how can I now start the application from GAC? As .net4.5 32 bit application i assumed that there would be a folder C:\Windows\Microsoft.NET\assembly\GAC_32\test - but there isn't
ngen display ..\text.exe
shows the original folder as ngen roots and a native image called Text, Version..., Culture
Maybe some information why I want to use ngen: An application needs a long startup time which should be reduced. On different places there is the information that ngen could speed up the startup time. If i try just the install as above and start from application directory - the startup time is neither changed to better or worse and I just don't know wether precompiled GAC version or jitted version is used. (That would be the bonus question - how do i know which one is used?)

How to debug custom bootstrap application?

I am using Burn for MSIs package. I am using Votive (Visual Studio) & my own custom BA instead of WiXBA. I tried to debug custom BA using Debugger.Launch(). But when I start debugging, error messages occur.
No symbols are loaded for any call stack frame. The source code cannot be displayed
I realized that package.exe links CustomBA dll which located at C:\Documents and Settings\user\Local Settings\Temp\{GUID}\. {GUID} is always changed. So, whenever I run package.exe, always directory is changed.
I think that is the reason to occur errors.
In Visual Studio, When I started package.exe with CustomBA dll which located at absolute path (.../Debug/bin/CustomBA.dll). But after execute the package.exe, it links to Local Settings\Temp\{GUID} directory. So, when we start debugging and attached to CustomBA dll, CustomBA dll's directory is dynamically changed and No symbols are loaded error occurs.
Why package.exe links dll which located at C:\Documents and
Settings\user\Local Settings\Temp\{GUID}\? Can we choose the path
for dll statically?
If we can't choose the dll path statically, how can I use debugging
functions for CustomBA?
To debug a Bootstrapper Application, you'll want both your Bundle .wixproj and BA .csproj (or .vcxproj if you're doing a native .dll) in the same solution and the Bundle project should be dependent on the BA project so rebuilds work correctly. The following steps should allow you to step into your code.
Note: Ensure you are not running Visual Studio elevated. If you have UAC disabled, re-enable it. These steps will not work correctly if Visual Studio is running elevated.
Rebuild the project. This ensures you have a Bundle created with an updated BA.dll inside it.
Right click on the BA .csproj in Solution explorer and select Set as StartUp Project. The BA .csproj should be bold.
Right click on the BA .csproj and choose Properties.
On the Properties for the BA .csproj select the Debug tab.
In the Debug tab, choose the radio button labeled Start external program
Browse to the path where your Bundle is built.
Now, you can press F5 and start debugging. Remember that any time you change the BA .csproj, you also need to ensure the Bundle .wixproj is rebuilt. Otherwise, the Bundle will launch with your old BA in it and the debugger will find the newly built BA's .pdbs don't match.
Extra credit: if you disable Just My Code in the debugger settings and download the pdbs.zip and sources.zip for the matching build of your WiX install, you can actually step through the Burn code as well as your BA to see how everything works together.
I followed Rob's suggestion in this post but sadly i couldn't get it to work for me (Visual Studio 2015, Wix 3.10.3, managed Bootstrapper Application using WixWPF). No breakpoints are ever hit. I noticed the debugger attaches itself to the wrong process, the installer has two running processes (im guessing the BA and the Bundle). When I changed the process the breakpoints were hit but my managed BA has code i want to debug before the debugger actually gets attached
Ive managed to find a solution where the application will not start until the debugger is attached. I put this code in my constructors code-behind file (in the DEBUG block) for my managed BA like so...
public MainWindow()
{
#if DEBUG
// Do not start until debugger attached
while(!System.Diagnostics.Debugger.IsAttached)
{
System.Threading.Thread.Sleep(1000);
}
#endif
InitializeComponent();
InstallData = new InstallerInfo();
}
Now when i compile my managed Bootstrapper Application (with Debug) along with the Bundle and run it, the application will not start until you attach to the managed Bootstrapper Application Tools > Attach to Process > Find your exe in the list.
You cannot run your custom BA in debug mode from Visual Studio.
What you can do is to run the generated exe file and then attach Visual Studio to the process which would let you debug it. (In the menu: Tools > Attach to Process > Find your exe in the list)
As many other answers suggested above, the debugger is attached to the process that runs installer executables. You will need to manually attach the debugger to the UI process that is spawned under a temp folder like many have done before.
To allow for child processes to be attached automatically without all the extra code mentioned, you do can as mentioned:
Install the visual studio extension called MicrosoftChildProcessDebuggingPowerTool.
Set the executable in debug start action just like Rob mentioned.
Enable native code debugging (important)
Turn on Child Process Debugging by
Debug -> Other Debug Targets -> Child Process Debugging Settings -> Enable child process debugging -> Save
The only thing which really works is:
protected override void Run()
{
Debugger.Launch();
}
in your bootstrapper UI application (BootstrapperApplication descendant). Then start the built bootstrapper.exe from the explorer and reuse your Visual Studio instance in "Choose Just-In-Time Debugger" window.
Don't forget to clean the solution before re-building. This prevents sometimes from debugging correctly.
PS: when there are problems with finding the correct pdb's of your bootstrapper UI assembly, choose the same architecture than the bootstrapper setup. Mixing architectures can lead to debugging problems.
Cheers
Rob's solution doesn't work. Approach of AhmedBM works but it still can be further streamlined so that VS runs WiX bootstrapper process and then immediately attaches to the child process.
public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
{
//kill old ones if any
System.Diagnostics.Process.Start(#"c:\Windows\System32\taskkill.exe", "/F /IM Bootstrapper.exe /T");
System.Threading.Thread.Sleep(1000);
//start new one
System.Diagnostics.Process.Start(#"<solution path>\src\Bootstrapper\bin\Debug\Bootstrapper.exe");
System.Threading.Thread.Sleep(1000);
foreach (Process proc in DTE.Debugger.LocalProcesses)
{
if (proc.Name.ToString().Contains(#".cr\Bootstrapper.exe"))
{
proc.Attach();
return;
}
}
System.Windows.MessageBox.Show("Bootstrapper Process was not found.");
}
The only problem is that you need DTE object. In earlier versions of VS we had Macroses where it was accessible. But in VS 2017 we don't have them. So, you can quickly make simple VS extension and add the command running the code there. Or use already existing extension, some of them allow to make custom commands.
Stick a MessageBox as the first line in your BA. Run the BA and the MessageBox will show up. Before hitting OK, From the menu DEBUG|Attach to Process, select your BA and Attach. Then hit the MessageBox's OK. Now your debugging!

Why is rubygem's "lib" directory not called "src"?

I've never had any problem with the basic gem tree structure, namely
bin (executables)
lib (source code)
test
...because I've always developed gems as libraries. However, I recently started to develop an application that ships as a gem.
This application has a "runner.rb" file (lib/mygem/runner.rb), that provides a method to run the application. The application is run from the bin/mygem file.
Now this bothers me. "runner.rb" is a file that is specific to our application, it is not a service or an API or any kind of support class for other to reuse (which is what library should be for, right?), yet its directory is "lib/mygem/runner.rb).
I've been reading a lot of definitions, and libraries are supposed to be support an application, not to be the application itself. We don't say "this is the library of my application", but "this is the source code of my application".
So my question is, why do we put the libraries AND source code in the same folder?
I hope I made my point clear, I'm sure there's a good reason behind this, and I'd be interested to hear your thought and to clear this out.
Thank you for reading this :)
After even further investigations, it turns out 'lib/' is called 'lib/' because it only contains definitions.
'bin' is a script that gets executed, like a 'main' function. Since it gets executed, no application logic should be in it, otherwise it's not easily testable.
Thus, all the application logic belongs to your application's library folder. The bin (main) file's only task is to instantiate your application's runner class and run it.