How to debug custom bootstrap application? - wix

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!

Related

Why does this explicitly-linked DLL delegate succeed in one program but not another?

I have 2 programs which share a project in which an API DLL is used to perform actions on files in another directory. The problem that I have is that this code works in one project, but in the other it fails:
moduleHandle = LoadLibrary(“api.dll”)
Earlier on, the program that fails failed to connect to the API DLL here so after comparing the Process Monitor logs of both I copied some DLLs into the same directory as it. It then succeeded, and the values of moduleHandle are now the same in both programs. Next:
methodPointer = GetProcAddress(moduleHandle, "NameOfSomeFunction")
delegateForSomeFunction = Marshal.GetDelegateForFunctionPointer(methodPointer, GetType(SomeFunctionType))
When we get to the delegateForSomeFunction, I can see that the value of _methodPtr in them is different from one program to another. Then when we get to invoking the delegate:
Dim argsArray() As Object = New Object() {directoryPath, errorFilePath}
Dim retVal As Short = delegateForSomeFunction.DynamicInvoke(argsArray)
In one program this just fails silently. I'm at a bit of a loss as to how to proceed. What should I do to investigate this further and how can I get it to work?
I’m running this on debug in Visual Studio 2013, and the project is in .NET 4.
Although copying the correct versions of dependencies from winsxs into the same directory of the API DLL did allow me to perform LoadLibrary without obvious errors, it caused more errors in the background.
The problem was in the manifest in the end. There was a post-build event that removed the manifest from the .exe in preparation for a deployment step that allowed you to specify different versions of the API present. Creating a proper appname.exe.manifest file specifying the dependent assemblies that I was failing to load normally, and then placing this into the same directory as the .exe, solved the issue.

T4 template cannot write file (file in use)

I have a simple T4 template that writes out a .cs file containing an AssemblyFileVersionAttribute, for the purpose of automatically incrementing the build number.
I have a pre-build event configured to use TextTransform.exe to run the template.
This worked fine in previous versions of Visual Studio, but in Visual Studio 2017 (the preview version, if it matters) I get this error on around 50% of builds:
The process cannot access the file 'C:\MyProj\Properties\BuildIncrement.cs' because it is being used by another process.
The only other process I guess that could be using the file is msbuild, but I would have thought it would wait until after the pre-build events complete before starting compilation.
Any ideas how I can resolve this?

Modify website MSBuild options to include configuration in path

I'm in the process of updating an old solution from Visual Studio 2005 to Visual Studio 2015, and I'm trying to reproduce as much of our old kludgy behavior as we safely can to minimize the downstream effects. I'm currently running into an issue with the Website Property Pages and MSBuild.
The path here is mostly correct, except that we want the configuration used to be in the path as well. So a Debug build will go into E:\Projects\...\PrecompiledWeb\Debug\MyService and a Release build will go into E:\Projects\...\PrecompiledWeb\Release\MyService. Is this doable? Is there a variable I can insert to make that determination when building?
We're using msbuild against the containing solution file (via TeamCity if it matters, but I can replicate it without it).
Edit: I've found the Debug.AspNetCompiler.TargetPath and Release.AspNetCompiler.TargetPath paths in the solution, but if I change them to be separate, the Debug one overrides the Release one when I next open the dialog.
When MSBuild starts building the project, it takes one or several project files. This dialog takes it parameters from MSBuild project file (you can edit it either from Visual Studio, or simply in every text editor). The project should have the property, called $(Configuration). You can use it in your output variable:
<OutputPath>E:\Projects\...\PrecompiledWeb\$(Configuration)\MyService</OutputPath>
One thing you must aware of is that the property $(Configuration) must be declared before the $(OutputPath) property.

Visual Studio 2015 locks DLL during debugging

I have 3 C# projects A, B, and C. Both A and B reference C. The references to C from A and B are set to "Copy Local" implying that after C is built to C.dll (in the output directory of C), it is copied to the output directory of A or B (whichever is being compiled)
I have 2 solutions, SA and SB. SA contains A and C and SB contains B and C. I launch 2 instance's of Visual Studio 2015. I open SA in one instance and SB in the other.
I am finding that if I Start Debugging (F5) A from SA, and then (while A is still debugging), make a change to C from SB and attempt to compile SB, I receive a compile error stating that C.dll can not be over-written because it is in use by another process (the instance of devenv.exe which is running SA).
This does not make sense to me because after compiling C to C.dll and copying to the output directory of A, Visual Studio should release the lock on the file.
I have verified (via the Modules window in SA) that the version of C.dll loaded is the one which has been copied to the output directory of A.
This started occurring yesterday when I began using Visual Studio 2015 (instead of Visual Studio 2013).
Does anyone have any ideas? My current solution is to run SA via CTRL-F5 (start without debugging), but this becomes annoying when I want to run SA and SB in debug mode simultaneously.
Thanks.
UPDATE
I did some research into why the "Edit and Continue" feature could cause the described behavior, and according to this page https://msdn.microsoft.com/en-us/library/ms164926.aspx> Edit and Continue allows one to make source code modifications while in a debugging session and have the results take effect without stopping debugging, recompiling, and restarting the debugging session (what a gnarly problem that must have been). With that feature enabled, Visual Studio might be required to recompile any dependent DLL's at any time which explains the lock.
I had the same problem. I changed my VS2015 settings and it seems the problem is gone:
disabled Options\Debugging\Edit and continue
-Options\Sourcecodemanagement from TFS to none-
-disabled Options\Debugging\Diagnostictools while debugging-
Not sure wich one caused the locking, but i suspect the diagnostictools wich I did not have in VS2013.
(The settings names I translated from German to english, don't know if it is exactly how they are called in english VS version.)
Edit:
As researched by Shea it was the Edit-And-Continue feature that locked the DLL.
in my case this was "Panda free Antivirus" Who was watching on the dll of the "C" project and this caused the error: "the process cannot access the file because it is being used by another process"
I had the same problem and none of the other recommended solutions I came across while searching the interwebs worked for me. Finally after "repairing" Visual Studio 2015 Enterprise, I tried launching Visual Studio in safe mode: devenv.exe /SafeMode
In safe mode I was able to finally build my solution, and when I started again without the switch, I was prepared to shut off extensions one by one until I found which one was the culprit. Luckily that was unnecessary and subsequent builds went off without a hitch.
In my case, the .pdb file was locked. This is not the same as the .exe getting locked as it should be when debugging.
Assuming it's just the .pdb, simply move it to a new folder (I dragged and dropped). Oddly enough, it cannot be deleted, but it can most certainly be moved! Once the .pdb file was gone, the assembly was able to compile again.
The alternative solution (and probably the least convenient) involves closing out of the project entirely, then opening it again (the .pdb file magically unlocks!).
Edit:
After happening a second time, moving the file did not work; it appears restarting the project is the only reliable way to go.

Embedding and Deploying ressources into VB project

I got a problem with some ressources. I got a simple .exe file, that is accessed by my application. So I saved the exe tool within my project folder and everything was simple. But now I want the exe to be embedded inside my application, to keep everything nice and clean.
I want my app to be a single file executable, that will deploy its dependencies and stuff on its own.
So read a little tutorial on stack: How to embed dll from "class project" into my project in vb.net
I got the .exe into my ressources and pasted the code into my ApplicationEvents.vb (don't kill me for CP ;) ). Next I tried to execute the whole thing, but nothing happend. By executing the application step by step (F8), I saw, that the AddHandler call is executed, but the Deploy Function gets never called.
Next I read a tutorial at MSDN:
https://msdn.microsoft.com/en-us/library/vstudio/e2c9s1d7%28v=vs.100%29.aspx
I tried to change the persitence mode of my ressource as described, but the Persistance option is disabled.
So what can I do to deploy my second .exe?