How to load symbols in Visual Studio 2012 - symbols

When I am debugging my app I see messages:
cannot find or open the PDB file
I seem to remember being able to specify the location of the PDB file while debugging the app. How can I do this? I'm using Visual Studio 2012.

Adding Symbols Location
Open Settings: Tools->Options -> Debugging -> Symbols and add directory, where your .PDB files are located.
screenshot of Visual Studio Interface where this menu located
You can add custom path, like for each project, and also you can edit common path, where Visual Studio will save all .pdb cache.
Making post-build script
I made in each project post-compile event, which copy all .pdb to one folder, by this i have all in one place. But you can store it separately, which i found not so convenient, as it require each time edit list of locations.
Example of post-debug script to copy .pdb and .dll to Symbols cache location:
xcopy /Y /R "$(TargetDir)$(ProjectName).pdb" "D:\VS_CACHE\"
xcopy /Y /R "$(TargetDir)$(ProjectName).dll" "D:\VS_CACHE\"
Solving problem if symbols not found
When you in debug mode, and for some reason symbols not found, it can be because of multiple reasons:
You have .pdb in Symbols cache, but it's outdated (you can get if this a case, if you put breakpoint in code and hover it)
You have multiple .dll which use this part of code (you can get if this a case, if you put breakpoint in code and hover it)
Symbols not loaded, in this case you can check it by going to: Debug-> Windows -> Modules and trying to load needed module.
screenshot of Visual Studio interface Modules -> Load Symbols
Making Debugging more easy:
To re-attach VS Debugger to running application, i recommend to use this free Visual Studio add-on (support VS 2015):
ReAttach: visualstudiogallery.msdn.microsoft.com/8cccc206-b9de-42ef-8f5a-160ad0f017ae
It will save you a lot of time! :)

Related

VS 2019 : Locals empty when debugging only in part of the code

I'm trying to debug as always in VS 2019. Recently, for some reason, when I hit a breakpoint in specific .cs files the Locals window is empty. However, in other files locals are available! When I use Immediate Window in the files where locals are empty, I get "Unable to evaluate expression". But same command in other parts of the code is working.
Context:
Project is a C# library (dll) which loads as a plug-in in another application (Revit)
The pdb file is located in the same directory as the dll
Project is using Fody Weaver. However I've been using it before and I weren't having debugging issues with it.
Advanced build settings are as follows:
I attach to the process using Debug > Attach to Process and the Automatic option:
I am attaching in the Debug mode and the dll is built using Debug mode as well.
The "Optimize Code" option is unchecked.
Things I have tried:
Enabled "Use Managed Compatibility" mode
Enabled "Suppress JIT optimization on module load"
Enabled "Just My Code"
Deleting breakpoints and creating the again
Cleaning solution and rebuilding
Restarting Visual Studio
Starting Visual Studio as an administrator
Updating Visual Studio to latest
Restarting my computer
Update:
I tried refactoring and splitting the file where locals aren't showing, into two files. To my surprise now the locals are showing both in the file where they weren't showing before and in the new file. However, the values shown are still weird. The type of objects are shown as float {class} and I can't expand to see their properties. See screenshot below from locals displayed in the new file:
So in my case the issue was a virus protection software called Cylance I had installed. I changed its settings to Monitor and in the Debug settings of VS, unchecked the "Use Managed Compatibility Mode" and the locals are all showing as expected again.

Automatically generate PDBs with dotPeek

I just discovered dotPeek and its symbol server greatness. The only drawback for me currently is that I need to manually add each DLL I want to debug and manually generate the PDB for it. It would be excellent if I could either do this in batch and just generate PDBs for a whole directory, or automatically generate them when requested in the symbol server (and the DLL is in the assembly explorer or something). Or another way to automate more of it. Is any of that possible?
The closest solution I've found, which will probably work for me, is to set the "Generate symbol files for" option in Tools > Options > Symbol Server to "Assemblies opened in the Assembly Explorer". This seems to automatically find anything in the explorer and generate a PDB on the fly if you open dotPeek and start the symbol server before you start Visual Studio.

Delphi: how to exclude units from debugger?

Sometimes as I am debugging step-by-step, just before a FormCreate Event or just after the FromDestroy the debugger starts to open DevExpress units (cxContainer.pas, ...) and so before FormCreate my "F8" leads me to cxContainer instead of going into the next line of my code.
(this is just an example, it can happen of course with any 3rd party library)
How do I tell the debugger "debug only my units" (only the pas files listed in dpr file?)
Of course sometimes it is useful to debug libraries, but in most cases it isn't.
You'd better follow VCL convention for your third-party components:
Change DCU output path in all the third-party packages to a folder different than the folder you store the PAS files.
Compile each package once in Debug mode, and save the generated DCU files in a folder (e.g. Debug DCUs).
Compile each package once again, but this time in Release mode, and save the generated DCU files in a folder (e.g. Release DCUs).
Go to Delphi options and add path of release DCUs to "Library path".
In Delphi options, add path of source files to "Browsing path".
In Delphi options, add path of debug DCUs to "Debug DCU path".
This way, Delphi will only see release DCUs of that third-party component when you are compiling your project, so the debugger cannot step into the source code.
On the other hand, since source path is included in "Browsing path", you can still navigate to the source code inside IDE by Ctrl+Click on unit name, or anything defined in those units.
If you want to debug component, you can go to "Project | Options | Delphi Compiler | Compiling", and enable "Use debug .dcus". This will force compiler to use "Debug DCU path" instead of "Library path".
VCL works the same, generally you don't step into VCL source code when you are debugging your project, but if you enable "Use debug .dcus" you can debug VCL source code too.
JVCL also organizes its packages and source code the same way.
EDIT:
If you take this approach, and want to have code browsing (Ctrl+Click) working; please take note that when you compile release version of packages, you must set Symbol Reference Info in "Project | Options | Delphi Compiler | Compiling" to "Reference Info"; otherwise, Ctrl+Click won't work for those units. By default, Release build configuration sets Symbol Reference Info to None.
A quick and simple solution is disabling the DEBUG switch ({$D-}) for any libraries you're using. Many libraries (including DevExpress) use a global include file, usually at the top of each source file, or right above or below the "unit" statement (e.g. unit cxContainer; {$I cxVer.inc} interface ). Open that include file (click on it and press CTRL-Enter) and add {$D-} right at the top, and comment out any existing {$D+}.
There is only one way to tell the compiler not to debug a unit: compile it without debug information.
If you have the source to your libraries, you can rebuild their package after having turned off the "include debug info" compiler option for each package in the library. If you are lucky, your libraries will include an .inc file which specifies the compiler options they need and which they include in each unit. In that case all you have to do is edit this inc file and rebuild all packages.
If you don't have the source to your libraries, the library makers may have provided two sets of dcu's: one compiled with, the other without debug information. In that case, simply point your library path to the one you need.
Turn off debug info in units you don't want the debugger going into.

How to correctly set "Directories/Conditionals" and "Library" path

How to set "Directories/Conditionals" in Project Options and "Library" path in Environment Options? Delphi help don't say much about these very important settings. I have all kind of strange errors because of wrong dependencies between my VCLs.
1.
I have merged a large set of 3rd party controls in a package called ThirdPartyPackages_D7.dpk. This is useful when I reinstall Delphi because I don't have to reinstall all those 3rd party VCLs amnually.
Then, I have my own controls in MyControls_D7.dpk which depends on the ThirdPartyPackages VCL. I also have another package BlgPackage.dpk that depends on MyControls.
At the end of the chain is my application (DPR project) which is using the controls in BlgPackage.
ThirdPartyPackages.dpk -> MyControls.dpk -> BlgPackage.dpk -> MyApplication.dpr
When I change/edit something to the second package (MyControls.dpk) and build the DPR application, it works. The compiler sees the changes made into that package.
However, if I close the project and load and compile the BlgPackage, it throws a nasty message that function xyz cannot be found in MyControls because I delete it (I have loaded MyControls' units into IDE in parallel with application's units). It seems that building the application only refreshes the DCU files for all used packages but not the DCP/BLP files.
How do I write and compile the code in the packages without explicitly loading the packages into the IDE and building them?
(Note: I have a nasty bug that does not allow me to switch between projects without restarting the IDE or to load a group of projects/packages (*.bpg) at the same time.)
2.
Another problem is that I want to store the compiled files (DCP/BPL/DCU) of a package in its folder (for example c:\MyProjects\Blg).
If I set the "Output directory", "Unit output directory" and "DCP output directory" boxes of BlgPackage package to its folder, not only its BPL/DCU/DCP files will be stored there but also the BPL/DCP files of MyControls will be stored there.
How can I have the binary files of each package in a separate folder?
Delphi 7, Win XP, all projects set to "Rebuild as needed"
You should explicitely compile packages - just compiling package files is not enough and as you have noticed leads to problems.
In modern Delphi versions you can create a project group (not sure about Delphi 7) that contains an application and packages you want to develop with the application, and you can easily switch between them and complile packages without need to close/reopen the application.
BlgPackage should not have an access to MyControls package sources (through "Library" path or by using the same directory), it should access only already compiled MyControls package, else the files from MyControls are compiled every time you build BlgPackage and the compiled files are stored in BlgControls DCU directory
ADDED
The "Library" path should lead to compiled files (.dcp, .dcu) and (if needed) resource files (.res, .dfm) only - it is enough to compile applications and packages that requires "MyControls" package. You can set the directory for compiled files directly in the package settings, and you should copy the resource files (if you need them) to the same directory manually. This directory should be included into "Library" path, or else you can use a directory already contained in "Library" path.
The "Library" path should not lead to source files (.pas) if you don't want these files to be compiled every time you build your BlgPackage or an application that requires "MyControls" package.
I use much simpler way for 3rd partie components and reinstalling Delphi.
Open regedit and find
[HKEY_LOCAL_MACHINE/SOFTWARE/Borland/Delphi/xxx] where xxx is version and export whole
branch.
Open file and delete keys LMKEY, LMLIC.
Copy C:\Program Files\Borland\Delphi x\Projects\Bpl folder to another location
Copy C:\Program Files\Borland\Delphi x\Imports to another location
Reinstall Delphi including any updates and GExpert
Import previously saved registries
Restore Bpl And Imports Folder
And whoala, Delphi is back with all 3rd partie components and IDE settings. Only limitation is that all components must reside in same folder before and after reinstalling Delphi.
This also restores TeamSource settings. If you are reinstalling Windows as well, be sure to make windows user with same user name as before.
MY solution (kinda dirty, but hey it works):
I put ALL 3rd party libraries.controls in a single package (a super-package). I put all my controls in a single package.
Now, when I migrate the packages to a different PC all I have to do is to copy/paste two folders and set two paths.
Works for me - others may not agree with it and I can't blame them. I blame the 'hell designers' from Borland/Embarcadero. If you look on StackOverflow you will see that until now nobody provided an elegant solution to this.

Delphi Rad Studio - Can I stop components being recompiled each time I compile/build

It might have something to do with library and other paths, but every time I build/compile software in DRS which uses a bought component like TMS controls the TMS controls keep getting recompiled, too.
How do I stop that?
Do you maybe include both source dirs and unit dirs of the components in your unitdir (Library path)
Try to only include the precompiled units in the unitdir (library path), and leave the sources of the components only in the browsing path. (for debugger use)
If your building with Packages you can change the TMS Package build control setting from "Rebuild as Needed" to "Explicit Rebuild".
If the source of the TMS package then changes your build will stop with:
Never-Build package 'NameOfChangedPackage' must be recompiled.
Another option that works if your building with or without packages, is to build with the DCUs. First you need to remove TMS Source directories from your Library path and project path. Then you need to open the TMS Package make sure it's project options knows of it's source. Then also set the DCU or Unit Output Directory to a new directory. With this you can rebuild TMS and find the new directory will be populated with the DCUs. Add the DCU Folder to your Library Path, and it won't recompile TMS when building your project.
Beware: If you compile TMS (or any other package) this way with debug information you may find yourself in the TMS source or the CPU Viewer. If you want to avoid the CPU Viewer and step in the TMS source you will need to set the browsing path. If you want to avoid stepping in the TMS Source all together make sure it's not compiled with debug information.

Resources