How can I eliminate warning NETSDK1137 in a .NET 5 WPF program? - wpf

I have the following warning in a WPF program that used to be built for .NET Framework 4.5 but is now being built for .NET 5.
Warning NETSDK1137 It is no longer necessary to use the Microsoft.NET.Sdk.WindowsDesktop SDK.
Consider changing the Sdk attribute of the root Project element to 'Microsoft.NET.Sdk'.
ListEditor
C:\Program Files\dotnet\sdk\5.0.100\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.DefaultItems.targets 376
Clicking the warning opens the file Microsoft.NET.Sdk.DefaultItems.targets at line 376. This file starts with a comment that says DO NOT MODIFY.
<!--
***********************************************************************************************
Microsoft.NET.Sdk.DefaultItems.targets
WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and have
created a backup copy. Incorrect changes to this file will make it
impossible to load or build your projects from the command-line or the IDE.
Copyright (c) .NET Foundation. All rights reserved.
***********************************************************************************************
-->
Line 376 falls in this XML element...
<Target Name="_CheckForUnnecessaryWindowsDesktopSDK"
BeforeTargets="_CheckForInvalidConfigurationAndPlatform"
Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals($(_TargetFrameworkVersionWithoutV), '5.0')) and '$(_MicrosoftWindowsDesktopSdkImported)' == 'true' and '$(TargetFrameworks)' == ''">
<NETSdkWarning ResourceName="UnnecessaryWindowsDesktopSDK" />
</Target>
There is a Project element that encloses the entire file. The element is this...
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...omissions...
</Project>
Since that element does not mention Microsoft.NET.Sdk.WindowsDesktop SDK the Project element does not seem to be the point at which the replacement Microsoft.NET.Sdk should be placed.
How do I eliminate the cause of this warning?

Your project, the .csproj file, not the MsBuild target xml. Change the top line to the following:
<Project Sdk="Microsoft.NET.Sdk">

This happens when you port the old project to .Net 5.
Perform a search of Project Sdk= to open your .csproj file,
and correct the 1st line to <Project Sdk="Microsoft.NET.Sdk">.
This should fix the warning.

Related

How to get current wpf project assembly version in wix toolset bootstrapper project?

I have a wpf project for which the installer is created by wix setup project. the wix setup project is compiled to get the .msi. The .exe is generated from the .msi file using wix bootstrapper project.Now my question is how to get the assembly version [assembly: AssemblyFileVersion("x.x.x.xx")] form wpf .cs file?
Andy is right, you will not be able to pull the version number from a .cs file as WiX does not compile or know anything to do with the C# code.
What you want to do is version your main executable file (presumably the .csproj application) using the assembly version properties. (These can be found in the project properties)
1) In the Product.wxs add said main executable as a file in the installer.
<Component Id='MainExecutable' Guid='*'>
<File Id='MainExe' Name='MainExe.exe' Source='Path-to-exe' KeyPath='yes' />
</Component>
2) Bind the version of the .msi to this main executable. This is done in the Version attribute of the Product element.
<Product Id="*" Name="My Product Name" Language="1033" Version="!(bind.FileVersion.MainExe)" Manufacturer="Debabrata" UpgradeCode="PUT-GUID-HERE">
Not that the value after the FileVersion is the ID of your file. This is important.
Now to use this version number in the bootstrapper project - the process is very similar.
1) Add the MSI to the bootstrapper.
<MsiPackage SourceFile="Path-to-msi" Id="MyMSI">
2) In the Version attribute of the Bundle element the binding should be.
<Bundle Name="My Bundle" Version="!(bind.packageVersion.MyMSI)">
Again, note how the ID matches.
Hope this helps!

WIX Setup doesn't build

I am using the WIX binaries from a local folder instead of the common installation. So i had to overwrite my Paths like this:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WixToolPath>$(TeamProjectBuildUtilsDir)Tools\WIX\</WixToolPath>
<WixTargetsPath>$(WixToolPath)Wix.targets</WixTargetsPath>
<WixTasksPath>$(WixToolPath)WixTasks.dll</WixTasksPath>
</PropertyGroup>
</Project>
It was working ok, but today i tried it again and get this:
System.IO.FileLoadException" in WixTasks.dll:
> Additional information: The file or assembly
> "file:///D:\Repos\MyProject\BuildUtils\Tools\WIX\candle.exe" or a
> dependency could not be found. To progress is not supported.
> (Exception of HRESULT: 0x80131515)
I am not very expirenced with WIX and don't know what to do. It worked fine.
My VS freezes after this build step.
If you downloaded the WiX binaries .zip, you need to "unblock" the file (remove the stream that indicates it was downloaded from the Internet). .NET won't load files that are marked as coming from the Internet.

Online-only ClickOnce app not updating through web link

I'm working on a ClickOnce app that's set to online-only. I publish it to an internal IIS server, with an HTML page in the same directory that contains this link:
The deployment looks like so, with all files except the HTML page generated by my project's publish target:
MyAppName
-> Application Files
-> MyAppName_2213_20_0_65
-> <The published files>
-> default.html
-> MyAppName.application
When I click the link, the app runs immediately without any confirmation prompt, and I see from the about box that it's the old version. When I browse to the file share and launch MyAppName.application by double-clicking on it in Explorer, I get the prompt asking me if I'd like to run it, and then it downloads and I get an error:
Unable to install this application because an application with the same identity is already installed. To install this application, either modify the manifest version for this application or uninstall the preexisting application.
As part of the build process, I set the InstallUrl property of the project to http://ourserver/MyAppName/MyAppName.application. Is that wrong? Should it be the HTML page that contains the link? How is it determining the "identity" that's generating a conflict?
Since the app's online-only, it's not installed and doesn't show up in the Programs and Features control panel (and therefore that part of the error message doesn't apply).
I'm new to ClickOnce, so let me know if I left out some helpful information.
Update
If I run mage -cc from a Visual Studio command prompt, the new version launches instead of the old one.
Update 2
As I poked around more, I'm seeing something that looks wrong, and could be the problem. I see the following two lines in my MyAppName.application file (the deployment manifest):
...
<assemblyIdentity name="MyAppName" version="1.0.0.0" ...
...
<dependency>
<dependentAssembly dependencyType="install" codebase="Application Files\MyAppName_2213_20_0_65\MyAppName.exe.manifest" size="82044">
<assemblyIdentity name="MyAppName.exe" version="1.0.0.0" ...
...
You can see the mismatch above. It's deploying to MyAppName_2213_20_0_65, but it thinks the version number of the exe is 1.0.0.0. I'm not sure why it thinks that. My project includes a file that gets generated as part of the build with this line:
[assembly: AssemblyVersion("2213.20.0.65")]
Then, to set the published version number, I have this in my csproj file:
<Target Name="BeforePublish">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="MyAppAssemblyInfo" />
</GetAssemblyIdentity>
<PropertyGroup>
<ApplicationVersion>%(MyAppAssemblyInfo.Version)</ApplicationVersion>
<InstallUrl>$(INSTALL_URL)</InstallUrl>
</PropertyGroup>
</Target>
Does the assembly version listed for my executable even matter? If it does, why is it stuck on 1.0.0.0, and could that be affecting the download of updated versions?
My second update put me on the right track. The problem was indeed the incorrect version number for the assemblyIdentity attributes. To fix it, I'm no longer using a BeforePublish target. Instead, I'm passing in the ApplicationVersion when I call MSBuild:
"%msbuild_path%" MyAppName.csproj /target:Publish /p:ApplicationVersion=%VERSION%

How to include heat generated wsx files in a smart way in wix installer?

It's a WPF application, with Wix Installer.
I have resourceses folder and I want to include these files in the installer to put next to the executable. I solved generating a resources.wxs file with necessary information about the files under the resources folder using the heat tool. I managed to includ into the main wxs file. For that reason I modified the .wixproj file, adding a before build target action to generate the wxs and include it in the main wxs.
Concern: .wixproj is kind of hidden, there thing that you cannot modify from visual studio, like adding a before build action (pre build action is a different story)
Question: How can I extract the before build action into a separate file?
The before build action in the .wixproj:
<Target Name='BeforeBuild'>
<Exec Command='"%WIX%bin\heat" dir $(SolutionDir)resources -dr ResourcesDir -var var.ResourcesDir -cg ResourceFilesGroup -gg -g1 -sfrag -srd -out $(ProjectDir)Resources.wxs' />
<ItemGroup>
<Compile Include='$(ProjectDir)Resources.wxs' />
</ItemGroup>
You can extract it into a separate fileā€”most project file types do that already. That's how they provide common targets to all projects of a type. A .wixproj has this:
<Import Project="$(WixVersionTargetsPath)" />
To augment your own, simply:
Create an XML file like:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name='BeforeBuild'>
<!-- tasks -->
</Target>
</Project>
Add an Import element inside the Project element and refer to that file:
<Import Project="custom.targets" />
If such a file primarily has Target elements, the convention is for it to have the file extension ".targets".
But there are two drawbacks with Visual Studio:
Visual Studio caches all the project file dependencies and runs the MSBuild internally. So, it you edit the external file, it won't be part of builds using Visual Studio until the project is next loaded. To quickly unload and reload a project, use the project context menu in the Solution Explorer. Workaround: Call MSBuild yourself.
When Visual Studio loads a project, if it includes non-standard external files, it gives a warning. (You can disable it per user by project file path, in the registry, if I recall.)
As an alternative to calling heat directly, you might want to look at the Harvest* targets that WiX provides. Note: As the documentation says, you don't invoke them directly (they're already invoked by the Build target); You simply add items to the ItemGroup they process and set properties they use.

How can I modify my C# project file so that Resources.resx is compiled into the satellite assembly for my UICulture?

I have a WPF application in C# that may need to be localized in the future. I want to support XAML/BAML localization and conventional resx localization. (The former is useful for most of the code, but some localized content comes from the view model, where it is more straightforward to use resx files.)
I have read the relevant parts of the WPF Localization Guidance. I have set the UICulture property in the msbuild file. I have added the following line to AssemblyInfo.cs:
[assembly: NeutralResourcesLanguage("en", UltimateResourceFallbackLocation.Satellite)]
I understand that I need to copy Resources.resx as Resources.en.resx so that my localized resources get written to the satellite assembly.
I have set the build target on Resources.resx to None and on Resources.en.resx to EmbeddedResource. The custom tool on Resources.resx is PublicResXFileCodeGenerator to generate the strongly typed resources class. I know that the generator only works on a file that doesn't have a culture-specific suffix.
At the moment I must manually keep Resources.resx and Resources.en.resx synchronized. They must be identical. (Rick Stahl explains that here.)
I have tried to modify my C# project file to copy the file automatically. However, I can't get this to work. I'm no msbuild expert! I added the following build target:
<Target Name="BeforeResGen">
<Copy SourceFiles="#(CopyAsLocalizedResources)" DestinationFiles="$(IntermediateOutputPath)Resources.$(UICulture).resx">
<Output ItemName="EmbeddedResource" TaskParameter="DestinationFiles"/>
</Copy>
</Target>
I changed the Build Action for Resources.resx from None to CopyAsLocalizedResources.
I see my Resources.en.resx file being copied to the intermediate directory during build, but my resources aren't found at runtime, and I get an exception. Presumaby they are never being compiled into the satellite assembly.
Can anyone help me achieve this using a modification to the project file?
The compiled language dll is expected to be in a folder named according to the ISO culture code for that culture. This culture-named folder is expected to be in the same directory as the parent assembly.
So, for some foo.dll:
(Default DLL)
bin\foo.dll
(Spanish(Mexico) Resources)
bin\es-mx\foo.Resources.dll
This folder structure and assembly will be made at compilation, so you just need to tweak your post-build action to move the dll in the culture folder to a matching folder in your target directory.
Note that you can perform this move via cp or other command line tools simply by typing the actions you need in the project post-build step box with the project properties in Visual Studio.
Eureka!
<Target Name="CreateLocalizedResources" BeforeTargets="AssignTargetPaths">
<Copy SourceFiles="#(CopyAsLocalizedResources)" DestinationFiles="$(IntermediateOutputPath)Resources.$(UICulture).resx" SkipUnchangedFiles="true" UseHardlinksIfPossible="true">
<Output TaskParameter="DestinationFiles" ItemName="GeneratedLocalizedResources" />
</Copy>
<ItemGroup>
<EmbeddedResource Include="#(GeneratedLocalizedResources)">
<ManifestResourceName>$(RootNamespace).Properties.Resources.$(UICulture)</ManifestResourceName>
</EmbeddedResource>
</ItemGroup>
<Message Text="Generated resources are: #(GeneratedLocalizedResources)" Importance="high" />
</Target>
I set the Build Action on my Resources.resx file to CopyAsLocalizedResources, and the custom build target handles tricking the build into making the proper satellite assembly.

Resources