We are in the process of switching Visual C++ projects to the vc141 toolchain (VS 2017). We have encountered a problem where Visual Studio is unable to use a .pdb file whose source .obj files don't exist anymore (for example because they have been compiled on a build server).
Let's take a very simple executable project:
#include <iostream>
int main() {
std::cout << "Hello world\n";
std::cin.ignore();
}
The .vcxproj file is all default, except for <GenerateDebugInformation>true</GenerateDebugInformation> to generate the pdb file.
Reproduction steps are, always using VS2017:
Compiling the project
Placing a breakpoint inside main
Removing the intermediate Debug/ directory containing the .obj files
Disabling build-on-run through the configuration manager (so it won't recreate them)
Starting a debug session
This works fine with the vc100 (VS 2010) toolchain, and the breakpoint works, but it immediately triggers the following error with vc141:
Error: Unable to open file
<path>\Debug\main.obj. Error code = 0x80070003.
This very generic error code corresponds indeed to FACILITY_WIN32/ERROR_PATH_NOT_FOUND. The path to main.obj can be found inside both versions of the .pdb file, thus it is unclear to us why VS suddenly breaks down when it doesn't find it.
The "Modules" view shows that the .pdb file seems to be loaded correctly. Additionally, the breakpoint's tooltip shows the following error:
The breakpoint will not currently be hit. Unexpected symbol reader error while processing MyUser_141.exe.
What could be a solution or a workaround for this problem, given that we cannot debug on the machine that compiles the binaries in our real-case application?
Here is the full .vcxproj file:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<RootNamespace>MyUser_141</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17134.0</WindowsTargetPlatformVersion>
<ProjectGuid>{90982029-29B8-4C9B-AFB7-B8F555F15C1E}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
Further research:
We tried some other toolchain versions. The bug is not present in v14.0 (VS 2015), but is present as soon as 14.11 (VS2017 15.3).
Using v141_xp, which as far as we can tell uses the same toolchain but older system libraries, works.
To fix this, make the following change in the property pages of the project(s) that build your executable(s) and DLL(s):
Configuration Properties -> Linker -> Debugging -> Generate Debug Info -> Generate Debug Information optimized for sharing and publishing
Static libraries, having no link step, don't need this. .EXEs and DLLs do.
When you specify /DEBUG with no additional options, the linker defaults to /DEBUG:FULL for command line and makefile builds, for release builds in the Visual Studio IDE, and for both debug and release builds in Visual Studio 2015 and earlier versions. Beginning in Visual Studio 2017, the build system in the IDE defaults to /DEBUG:FASTLINK when you specify the /DEBUG option for debug builds. Other defaults are unchanged to maintain backward compatibility.
Source : https://developercommunity.visualstudio.com/content/problem/259283/error-unable-to-open-file-mainobj-error-code-0x800.html
Related
This question already has answers here:
How to deploy a Win32 API application as an executable
(3 answers)
Closed 11 months ago.
This post was edited and submitted for review 11 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I'm building a Windows executable with VS 2019. When I run it on my machine, it works, but I'm not 100% sure it will work for end users who don't have vc_redist.x64.exe version 2019. (Especially users on Win7 - it's in a niche where users still use this version).
How to statically link everything so that the end user will never be asked to download and install Visual C++ Redistributable "vc_redist"?
I'm using msbuild.exe, and no IDE. Which setting to add in the .vcxproj file or in the .cpp file to enable full static linking, to prevent the need for vcredist?
My .cpp code asks for these libraries:
#pragma comment(lib, "comctl32.lib")
#pragma comment(lib, "winmm.lib")
Sample .vcxproj:
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Targets" />
</Project>
Note: it is linked with the topic How to deploy a Win32 API application as an executable, but here it's about doing it specifically directly from the .vcxproj file and without the IDE.
Add a specific ClCompile property for the compilation configuration:
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
</ItemDefinitionGroup>
</Project>
Possible values are here: runtimeLibraryOption Enum
(remove the "rt" prefix)
rtMultiThreaded 0 : Multi-threaded (/MT)
rtMultiThreadedDebug 1 : Multi-threaded Debug (/MTd)
rtMultiThreadedDebugDLL 3 : Multi-threaded Debug DLL (/MDd)
rtMultiThreadedDLL 2 : Multi-threaded DLL (/MD)
More info about MT / MD can be found here: /MD, /MT, /LD (Use Run-Time Library)
After upgrading to VS 2019 I'm trying to make the C++ warnings useful again by disabling some that I don't care about, for example C26812
I know I could go to every project's property page and add this string to "Disable Specific Warnings" but that would be too much duplication (I've got a lot of projects). So instead I'm trying to change the DisableSpecificWarnings variable which is common to all Projects: 4996;6031;%(DisableSpecificWarnings)
How and where can I change this global variable in Visual Studio 2019 ?
For anyone interested, I ended up creating one GLOBAL.props file which is shared across projects.
To add this sheet, select project go to "Property Manager", select the Project and do "Add Existing Property Sheet". For example DisableSpecificWarnings used by all sub-projects is defined here. For further information on Compile and Link properties, see MSBuild documentation:
Clcompile: https://learn.microsoft.com/en-us/visualstudio/msbuild/cl-task?view=vs-2019
Link: https://learn.microsoft.com/en-us/visualstudio/msbuild/link-task?view=vs-2019
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup>
<ClCompile>
<DisableSpecificWarnings>4675;4541;4702;4267;4996;26812;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup />
</Project>
Project defaults come from several .props files, organized by scope, language and platform. The location (and even presence) of those .props files has changed between versions, and can depend on the history of past versions installed prior to VS 2019.
One (safer) way to identify the default .props being actually used is to create a new C++ project and look at the <Import Project ... /> lines in the generated .vcxproj file. For example, I am getting the following on my machine, in increasing order of specificity.
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
The last one is supposed to be the most specific, carrying the per-user per-platform settings. It appears to no longer be created with fresh VS 2019 installs, but it is inherited from prior versions and is still recognized when present (see Microsoft.Cpp.Win32.user.props file missing for example).
To see what "$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" expands to, open the project settings and pretend to change any of editable paths in the configuration, then click Edit in the dropdown menu and paste the .props path in the edit box. The actual path will show right below it, for example C:\Users\<user name>\AppData\Local\Microsoft\MSBuild\v4.0\Microsoft.Cpp.Win32.user.props.
Find the file on disk, or create it if it doesn't exist already, and insert the following under Project/ItemDefinitionGroup/ClCompile.
<DisableSpecificWarnings>26812;%(DisableSpecificWarnings)</DisableSpecificWarnings>
If the .props file did not exist and you had to create it from scratch, the complete file would be:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
<ClCompile>
<DisableSpecificWarnings>26812;%(DisableSpecificWarnings)</DisableSpecificWarnings>
</ClCompile>
</ItemDefinitionGroup>
</Project>
In order to modify the per-machine defaults, rather than the per-user ones, follow the same steps but use one of the $(VCTargets) files instead.
I'm trying to migrate a .NET core library project from VS2015 to VS2017, which will cause the project.json file to be converted into a .csproj file.
Now, the project is referencing two libraries that I've created, and when build are being pushed to VSTS package manager.
When working with the project in Visual Studio I prefer to have the to referenced projects added to my solution, so I can work on the code in the same solution. At the same time I'd like the project to reference the packages, so when build on VSTS it'll pickup the packages instead.
With the project.json file, this worked fine, nuget restore (I'm using nuget restore, since dotnet restore cannot autheticate to VSTS packagemanager) would just restore the packages and I could build it.
Now with the .csproj file, the references projects are added like this:
<ItemGroup">
<ProjectReference Include="myliba\src\myliba.csproj" />
<ProjectReference Include="mylibb\src\mylibb.csproj" />
</ItemGroup>
which will make 'nuget restore' try to restore packages for these projects as well.. but since these projects are in another repository, they are not (and should not) being downloaded from the repository, and 'nuget restore' fails with the error:
Errors in C:\a\1\s\src\mylib\mylib.csproj
Unable to resolve 'C:\a\1\myliba\src\myliba' for '.NETCoreApp,Version=v1.1'.
Unable to resolve 'C:\a\1\mylibb\src\mylibb.csproj' for '.NETCoreApp,Version=v1.1'.
How do I make nuget ignore these ProjectReferences, and make it get the libraries from the VSTS package manager instead?
One solution:
If I define a variable on VSTS called 'BuildSystem' and set it to VSTS, then I can check for this in my .csproj
<ItemGroup Condition=" '$(BuildSystem))' == '' ">
<ProjectReference Include="myliba\src\myliba.csproj" />
<ProjectReference Include="mylibb\src\mylibb.csproj" />
</ItemGroup>
Though it means that I have to tailor all my .csproj manually, which is not optimal
You are using project reference (ProjectReference) instead of package reference. You need to install the corresponding packages from VSTS package feed.
The sample project file code (project and package references):
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup Label="Globals">
<SccProjectName>SAK</SccProjectName>
<SccProvider>SAK</SccProvider>
<SccAuxPath>SAK</SccAuxPath>
<SccLocalPath>SAK</SccLocalPath>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<PropertyGroup>
<PackageTargetFallback>$(PackageTargetFallback);portable-net45+win8+wp8+wpa81;</PackageTargetFallback>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ClassLibraryCore2017" Version="1.0.0" /><!--package reference-->
<PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" />
</ItemGroup>
<ItemGroup>
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ClassLibrary1\ClassLibrary1.csproj" /><!--project reference-->
</ItemGroup>
</Project>
You can refer to these steps to achieve your requirement:
Add VSTS feed to Nuget source by calling
this command
nuget sources add -name [feed name] -source [your vsts feed] -username test -password [personal access token] -StorePasswordInClearText
Install packages from your VSTS feed to your project via VS 2017.
Add Nuget.config (in %appdata%\Nuget folder) to the source control (at the same level of solution file)
Check in changes
If you are using NuGet Installer step/task, specify NuGet.config in Path to NuGet.Config input box.
If you are using .Net Core (Preview) step/task, specify this arguments in Arguments input box: --configfile ..\Config\NuGet.Config
I'm having a hard time trying to figuring out what field to fill into an xml file I'm creating. I have been trying to follow 'Using MSBuild to Create a Visual C++ Project'(http://msdn.microsoft.com/en-us/library/dd293607.aspx) but I'm stuck on the xml part.
So the fields are:
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.default.props" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ItemGroup>
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="main.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Targets" />
</Project>
The only part I know I have to change is the Item group portion to match all my .cpp and .h files. Are all the fields necessary? Can you give an example for the $(VCTargetsPath) in each of the Import Projects? This seems simple but only after the first time of doing it. Thanks.
VCTargetsPath is property of the toolset, defined in registry. In your case, for ToolsVersion="12", registry location would be HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSBuild\ToolsVersions\12.0. Normally the toolset is configured automatically when you install appropriate SDK.
I honestly never created a C++ project file with msbuild in the editor, always let vs do it for me and include/invoke the vcxproject file through my seperate custom build file... however, the TargetPath, is the directory of the configured targets for C++ of MSBuild, on my machine with vs 2013 installed its (configured to use the vc++ 12.0 tools): C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V120.
These imports define the ClInclude task and all other C++ related tasks your tools support.
I have a program which must build as 32 bit. It gets shipped with an x64 application. As a result, there is an installer which gets a bitness.
The installer is built with a wixproj that must be built with /p:Platform=x64 -- but the vcxproj needs to build as x86.
I tried forcing Platform to be x86 or Win32 by setting it explicitly:
<PropertyGroup>
<Platform>Win32</Platform>
</PropertyGroup>
but it appears that the command line switch that got passed to the wixproj "wins" when building.
Is there some way that the project file can force Platform to be Win32 no matter what is specified on the command line?
(for csproj I was able to do this:
<PropertyGroup>
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
but that doesn't have any effect on C++ it seems)
Finally figured this out. MSBuild has a setting TreatAsLocalProperty that allows a project file to override any variable, which goes into the Project node at the beginning of the file.
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build"
ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
TreatAsLocalProperty="Platform"> <!-- !!! -->
<PropertyGroup>
<Platform>Win32</Platform>
</PropertyGroup>
<!-- Now Platform is Win32 no matter what! -->
</Project>