izPack creates an uninstaller that doesn't work in Windows "Programs and Features" - uninstallation

I'm working on a graphic installer for a java project using izPack 4.3.4, the installation goes well but when I try to uninstall it by clicking on his reference in "Programs and Features" window it shows the message:
Error: Unable to access jarfile C:\Program Files (x86)\myproject\uninstaller\uninstaller.jar
The fact is that I choosed to put and rename the uninstaller in the root install path of my program and not in \uninstaller dir. See the XML:
<info>
...
<uninstaller name="uninstall.jar" write="yes" path="${INSTALL_PATH}" />
...
</info>
And, in fact, uninstall.jar file is created in C:\Program Files (x86)\myproject\ and it works if I double click on it or throught the Start Menu. I think izpacks writes the wrong data in the Windows's registry to reference it in "Programs and Features"... but I don't know why...

If you're installing using IZPack on Windows, you can (should) have a RegistrySpec.xml. That guy writes all the registry entries you need. Windows looks for a Registry Value "UninstallString" as the file to run to kick off your uninstall, and you likely need to overwrite that. For example on mine:
<pack name="UninstallStuff">
<!-- Special "pack", if not defined an uninstall key will be generated automatically -->
<value name="UninstallString"
keypath="SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$APP_NAME"
root="HKLM"
string="$INSTALL_PATH\uninstall\uninstaller.cmd"/>
<pack name="UninstallStuff">

Related

How do I get a console project to group my appsettings.json files?

If I start a new web api project, the appsettings files are grouped together. However, I'm creating a working project from the console app template and when I create the appsettings files manually, the do not group together. I think back in older versions, there was something I'd put in the csproj file, but I don't know how to do it in .net core and I'm not seeing anything in properties or configurations
In the project file of your solution you can edit or add an <ItemGroup> element within the <Project> element. This worked for me:
<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="appsettings.*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<DependentUpon>appsettings.json</DependentUpon>
</Content>
</ItemGroup>
Please Note that my console project targets .Net Core 2.0 and is running in Visual Studio Pro 2017 Version 15.7.5.
Also, if your Solution Explorer doesn't immediately refresh try unloading and reloading the project.
Using an <ItemGroup> with <Content> as suggested gave me an error (in Visual Studio 2019) about "Duplicate 'Content' items included". It turns out the .NET SDK includes 'Content' items from your project directory by default. Setting the EnableDefaultContentItems property to false seems a bit rigid, so now I include the items as <None>.
<ItemGroup>
<!-- Group AppSettings in Console project. Use None to prevent "Duplicate 'Content' items were included" when using (default) EnableDefaultContentItems=true -->
<None Include="appsettings.*.json">
<DependentUpon>appsettings.json</DependentUpon>
</None>
</ItemGroup>
This does show the files grouped, but shows their properties with Build Action 'None' and 'Do Not Copy' in the Solution-explorer, so I guess that's the price for wanting them to group?
FWIW: a file-nesting rule as suggested in appsettings-json-not-in-hierarchy
will not show the files as grouped/nested, but it will make it collapse if the solution-explorer collapse-button is pressed.
You just need to click the File Nesting icon, and choose "Web"

How do I configure a Server-Side Console Project in EWL?

I know I have to define this section in Development.xml:
<serverSideConsoleProjects>
<project>
<Name>Program</Name>
<AssemblyName>Assembly</AssemblyName>
</project>
</serverSideConsoleProjects>
Do I have to do anything else? What effect does this actually have on the solution or on any of the Package Manager Console operations?
Essentially, declaring a server-side console project causes that project's build output to be included in the Logic Packages folder that gets created in your solution folder by the ExportLogic console operation. To my knowledge there is nothing else that EWL does right now with these projects.

Setting Code Analysis settings in TFSBuild.proj

I am trying to set/override some settings in our TEST installation of TFS with regards to forcing Code Analysis and assosicated settings during the build process (regardless of the setting sin the project file)
We currently use in our TEST TFS installation:
Visual Studio 2012 Ultimate on our developer machines AND build server
Have TFS 2012 installed on one server (application and data layer)
Have TFS 2012 build service (controller and agent) installed on another server
We can compile sample .net 4.5 projects (class libraries (DLLs), web applications etc) as expected. This is solely to do with overriding associated Code Analysis settings (hopefully).
Scenario 1 - In our sample applications on our developer machines when you select the project settings (right click -> properties in solution explorer), go to the Code Analysis tab if I turn on the "Enable Code Analysis on build" and select a Rule set from the drop down is performs as exepcted, hence it will generate some warnings. This technical adds <RunCodeAnalysis>false</RunCodeAnalysis> to the *.csproj file if opened up in notepad. If the build is executed to compile the sample project/solution then Code Analysis is performed as expected. I do NOT want to do this on every project because a developer could turn it off (although I am looking to have check-in policies and/or private/gated checkins as well to force this anyway).
Scenario 2 - I can disable the "Enable Code Analysis on Build" checkbox and force code analysis in our TFSBuild.proj file (we (will) use the default upgradetemplate.xaml as our process definition because we will be upgrading from TFS 2008 on our LIVE TFS installation) by having:
<RunCodeAnalysis>Always</RunCodeAnalysis>
This works and this is how we will force (lessons still to be learned :-)) Code Analysis on our builds.
The problem then comes when setting other assosicated Code Analysis settings. For example which default rule set(s) to apply/use or treat CA warnings as errors. Some of these settings can be set either in VS or all of them by editting *.csproj in notepad. If i edit the *.csproj then these values are used in the build as expected (as well as locally on the developer machine). This is not ideal as I want to do it centrally in TFSBuild.proj without having to edit every project file. I believe I can use settings such as in my TFSbuild.proj file:
<PropertyGroup>
<RunCodeAnalysis>Always</RunCodeAnalysis>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisTreatWarningsAsErrors>true</CodeAnalysisTreatWarningsAsErrors>
</PropertyGroup>
But they don't appear to work or I am putting them in the wrong place? How do I fix/use them correctly?
FYI i build my solutions in TFSBuild.proj by:
<Project DefaultTargets="DesktopBuild" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\TeamBuild\Microsoft.TeamFoundation.Build.targets" />
<ItemGroup>
<SolutionToBuild Include="/some folder/some solution.sln" />
<ConfigurationToBuild Include="Debug|Any CPU">
<FlavorToBuild>Debug</FlavorToBuild>
<PlatformToBuild>Any CPU</PlatformToBuild>
</ConfigurationToBuild>
</ItemGroup>
</Project>
On the build server I did find reference to the target file for Code Analysis at c:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\CodeAnalysis but I dont want to change the default behaviour on the build server (although it does work when I do). The condition for example for CodeAnalysisTreatWarningsAsErrors must be getting evaluated as false. Its like my values are not read from TFSBuild.proj but are from the .csproj file.
Any questions feel free to ask and thanks in advance
I had what I think is a similar problem with Cruise Control not compiling using the CODE_ANALYSIS compilation symbol, even if "Enable Code Analysis on Build (defines CODE_ANALYSIS constant)" was checked in VS.Net.
It looks like whether it is check or not, CODE_ANALYSIS is actually not explicitly added to the list of compilation symbols in the csproj (even if it appears in the text box "Conditional compilation symbols"), only <RunCodeAnalysis>true</RunCodeAnalysis> is added.
When compiling through VS.Net, the CODE_ANALYSIS is automatically added, but not when using MSBuild, which is what Cruise Control uses.
I eventually changed in VS.Net the "Conditional compilation symbols" from "CODE_ANALYSIS;MySymbol" to "MySymbol;CODE_ANALYSIS". Doing that forced CODE_ANALYSIS to also appear in the csproj.
I remember having a similar problem - but not having the time to investigate it, I worked around it by calling FxCop directly using the exec task. I'll just give you the highlights, omitting the specification of some properties, I hope the names are clear.
I created an ItemGroup of the output dlls, FilesToAnalyze, and fed it to FxCop in a way similar to:
<PropertyGroup>
<FxCopErrorLinePattern>: error</FxCopErrorLinePattern>
<FxCopCommand>"$(FxCopPath)" /gac /rule:"$(FxCopRules)" /ruleset:="$(FxCopRuleSet)" #(FilesToAnalyze->'/file:"%(identity)"', ' ') /out:$(FullFxCopLog) /console | Find "$(FxCopErrorLinePattern)" > "$(FxCopLogFile)"</FxCopCommand>
</PropertyGroup>
<Exec Command="$(FxCopCommand)"
ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="FxCopExitCode"/>
</Exec>
<ReadLinesFromFile File="$(FxCopLogFile)">
<Output TaskParameter="Lines" ItemName="AllErrorLines"/>
</ReadLinesFromFile>
I could then determine the number of errors in the output using an extensionpack task:
<MSBuild.ExtensionPack.Framework.MsBuildHelper TaskAction="GetItemCount" InputItems1="#(AllErrorLines)">
<Output TaskParameter="ItemCount" PropertyName="FxErrorCount"/>
</MSBuild.ExtensionPack.Framework.MsBuildHelper>
and create a failing build step for each error:
<BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
BuildUri="$(BuildUri)"
Id="$(FxCopStep)"
Status="Failed"
Message="FxCop Failed: $(FxErrorCount) errors."/>
<BuildStep TeamFoundationServerUrl="$(TeamFoundationServerUrl)"
BuildUri="$(BuildUri)"
Status="Failed"
Message="%(AllErrorLines.Identity)"/>
By doing code analysis on the build server this way, we also avoided having to configure each project separately. We isolated all this in a separate .targets file, so adding code analysis to a solution was a matter of importing that file, and perhaps adjusting the behavior by setting appropriate properties.

Automatic copy files to output during application building

There is Copy to Output Directory property for files in C# projects. But in VC++ projects it is absent. I know, that I can use Build events in VC++ and write there something like
xcopy /y /d %(FullPath) $(OutDir)
Is there a way to avoid the use of CMD (and other scripting methods)? Can msbuild do something to help in this case?
Can MSBuild do something to help in this case?
Using MSVC 2012, this worked for me:
Assumed you have a file "Data/ThisIsData.txt" in your c++ Project.
Unload the project (right click --> Unload Project).
Edit project XML (right click --> Edit .vcxproj)
Now you see the projects MSBuild file as XML in your editor.
Find "ThisIsData.txt". It should look something like:
<ItemGroup>
<None Include="Data\ThisIsData.txt" />
...
</ItemGroup>
Now add an other item group like this:
<ItemGroup>
<Content Include="Data\ThisIsData.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
...
</ItemGroup>
Reload the project and build.
Your file "ThisIsData.txt" should get copied to $(OutDir)\Data\ThisIsData.txt.
Why duplicating the ItemGroup?
Well if you simply change the None include to a content include, the IDE does not seem to like it any more, and will not display it. So to keep a quick edit option for my data files, I decided to keep the duplicated entries.
In VS 2015 it is possible to give C projects the functionality that is in C#.
(Idea from building off of jochen's answer.)
Instead of adding another ItemGroup, modify the given itemgroup adding a CopyTo element. I.E, using his example, simply enhance the original entry to:
<ItemGroup>
<None Include="Data\ThisIsData.txt" />
<DeploymentContent>true</DeploymentContent>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
...
</ItemGroup>
No other ItemGroup required. By adding the CopyTo element, you add an "Included In Project" property.
In Visual Studio 2017 you can do this in the IDE. I am not sure about earlier versions.
Simply add the file as an included project file so it shows in the Solution Explorer. Then right click on the file and select the Properties menu.
Change the Content to "Yes" and change the Item Type to "Copy file"
If you look at the changes it made to the project file you can see it added this:
<ItemGroup>
<CopyFileToFolders Include="Filename.txt">
<DeploymentContent>true</DeploymentContent>
<FileType>Document</FileType>
</CopyFileToFolders>
</ItemGroup>
It depends on what version of Visual Studio you are using. Format of VC++ project file in Visual Studio 2008 is not MSBuild and so using xcopy in PostBuildStep is a good choice.
VC++ project in Visual Studio 2010 has MSBuild format. Thus, there is functionality of MSBuild Copy task.
Below is a sample:
<Copy
SourceFiles="%(FullPath)"
DestinationFolder="$(OutDir)"
/>
If the destination directory does not exist, it is created automatically
An MSDN Copy task reference is here
Following henri-socha's answer about VS2015 (and probably VS2013 and VS2012, or anything using MSBuild style projects), the ItemGroup item type is important.
Specifically <Text> items do not seem to be copied, whereas <Content> items do.
So, for a project directory Data containing a text file ThisIsData.txt, this will create a subdirectory Data under the $(OutDir) directory and copy the file ThisIsData.txt from the project into it if it's newer:
<ItemGroup>
<Content Include="Data\ThisIsData.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
This won't, although it is what the Visual Studio IDE will insert if you add the text file to your project, and set the Content property to True.
<ItemGroup>
<Text Include="Data\ThisIsData.txt">
<DeploymentContent>true</DeploymentContent>
</Text>
</ItemGroup>
So in other words you need to add the file via the IDE to make it realise the file is included in the project (which adds <Text> tag ItemGroup), and then open the project in a text editor and add the <Content> tag ItemGroup to get it to do what you want.
I'm not sure what the <DeploymentContent> tag actually does. It may be a remnant since the only MSDN reference I could find considers it archived: https://msdn.microsoft.com/en-us/library/aa712517.aspx
In visual studio 2019 after setting the file as "Include in project" you can edit the properties an select as Item Type "Copy file" (as shown in https://i.stack.imgur.com/vac2b.png)
This avoids the manual vcxproj file edition.
You can specify copying in the project file as Jeff G answered in another question:
In the *.vcxproj file, change:
<Text Include="Filename.txt" />
to:
<Content Include="Filename.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Then in the *.vcxproj.filters file, change:
<Text Include="Filename.txt">
<Filter>Resource Files</Filter>
</Text>
to:
<Content Include="Filename.txt">
<Filter>Resource Files</Filter>
</Content>
where the <Text ...> tag is for specified text files (it'll be <Image ...> for image files etc.)
If it's a COM dll, you can add it to the root of your project, mark it as 'Content' and set copy to output directory to 'Always'. I had to do this for signature capture COM assembly.

MSBuild: Custom.After.Microsoft.Common.targets for native C++ projects in VS2010

I've read about the use of "Custom.Before.Microsoft.Common.targets" and "Custom.After.Microsoft.Common.targets" in order to execute a custom target before/after every project build and I would like to use this technique in order to change version info while building on our TeamCity build server.
The problem is that although it works for C# projects, it doesn't seem to work for native C++ projects.
After some digging around in the Microsoft.Cpp.targets file I found out that for native C++ projects this seems to be implemented through setting $(ForceImportBeforeCppTargets) and $(ForceImportAfterCppTargets).
I can't seem to find a single piece of information on the web about this technique for native C++ apps though, so I'm asking if I'm looking in the right direction or not.
Any help is appreciated.
For VC++ projects it is a bit different. You define a file to be imported either at the beginning or at the end of the project. To use this approach you need to define values for the properties ForceImportBeforeCppTargets or ForceImportAfterCppTargets. For example if you want a file to be included at the beginning of the project you can pass in the value at the command line. For example I just created a dummy VC++ project named CppTets01. Then I created the two sample files below.
Before.proj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CustomTargetInBefore" AfterTargets="Build">
<Message Text="From CustomTargetInBefore" Importance="high"/>
</Target>
</Project>
After.proj
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CustomTargetInAfter" AfterTargets="Build">
<Message Text="From CustomTargetInAfter" Importance="high"/>
</Target>
</Project>
Then I executed the following command:
msbuild CppTest01.vcxproj
/p:ForceImportBeforeCppTargets="C:\Temp\_NET\ThrowAway\CppTest01\CppTest01\Before.proj";
ForceImportAfterCppTargets="C:\Temp\_NET\ThrowAway\CppTest01\CppTest01\After.proj"
The result was
C:\Temp_NET\ThrowAway\CppTest01\CppTest01>msbuild CppTest01.vcxproj /p:ForceImportBeforeCppTargets="C:\Temp_NET\ThrowAway\CppTest01\C
ppTest01\Before.proj";ForceImportAfterCppTargets="C:\Temp_NET\ThrowAway\CppTest01\CppTest01\After.proj"
Microsoft (R) Build Engine Version 4.0.30319.1
[Microsoft .NET Framework, Version 4.0.30319.1]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 10/18/2010 8:32:55 AM.
Project "C:\Temp\_NET\ThrowAway\CppTest01\CppTest01\CppTest01.vcxproj" on node 1 (default targets).
InitializeBuildStatus:
Creating "Debug\CppTest01.unsuccessfulbuild" because "AlwaysCreate" was specified.
ClCompile:
All outputs are up-to-date.
All outputs are up-to-date.
ManifestResourceCompile:
All outputs are up-to-date.
Link:
All outputs are up-to-date.
Manifest:
All outputs are up-to-date.
FinalizeBuildStatus:
Deleting file "Debug\CppTest01.unsuccessfulbuild".
Touching "Debug\CppTest01.lastbuildstate".
CustomTargetInBefore:
From CustomTargetInBefore
CustomTargetInAfter:
From CustomTargetInAfter
Done Building Project "C:\Temp\_NET\ThrowAway\CppTest01\CppTest01\CppTest01.vcxproj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.21
As you can see from the output the targets were successfully injected into the build process. If you want to relate this back to Custom.Before.Microsoft.Common.targets and Custom.Before.Microsoft.Common.targets then you should know that the technique used there is a bit different. Specifically if you create those files they are automatically imported into every C#/VB.NET project. In this case you have to set this property. You really have two options here:
You can set this property as an environment variable
You can use another technique, ImportBefore & ImportAfter which is specific to VC++
For #1 let me explain a bit. In MSBuild when you access a property with the syntax $(PropName) then if a property with the name PropName doesn't exist MSBuild will look up in the environment variables to see if such a value exists, if it does then that value is returned. So if you have a build server in which you want to include a file for each VC++ build, then just create those properties as environment variables. Now for the other technique.
ImportBefore/ImportAfter
In VC++ a new concept is introduced. In Microsoft.Cpp.Win32.targets you can see the declaration at the top of the .targets file.
<Import Project="$(VCTargetsPath)\Platforms\Win32\ImportBefore\*.targets"
Condition="Exists('$(VCTargetsPath)\Platforms\Win32\ImportBefore')" />
Then there is one towards the bottom
<Import Project="$(VCTargetsPath)\Platforms\Win32\ImportAfter\*.targets"
Condition="Exists('$(VCTargetsPath)\Platforms\Win32\ImportAfter')" />
A similar import declaration exists for the other target platforms as well. Take a look at the files at %ProgramFiles32%\MSBuild\Microsoft.Cpp\v4.0\Platforms\ for the specific names.
With this technique if you want a file to be imported then simply create a file that ends with .targets and place it into the appropriate folder. The advantage of this is that it will be imported into every VC++ build for that platform, and that you can create many different files. The drawback is that you have to place them in those specific folders. That's the main difference between both techniques. With this first technique you can specify the file location via property and its not automatically included for every build, but for the second approach it is but you cannot change the location
You can also add project content into one of *.props files from directory %LOCALAPPDATA%\Microsoft\MSBuild\v4.0\
It make same effect.