oleg-shilo / wixsharp

Framework for building a complete MSI or WiX source code by using script files written with C# syntax.
MIT License
1.03k stars 168 forks source link

Using PackageReference instead of packages.config doesn't appear to work #620

Closed jonreis closed 5 years ago

jonreis commented 5 years ago

Hello @oleg-shilo

I know you have covered this before, but I cannot get PackageReference to work properly with Wixsharp. I always get the error below. I have tried creating new setup projects from the Wixsharp templates, however; they all seem to use Package.config.

Any hints on how to solve this issue?

Severity Code Description Project File Line Suppression State Error The "SetEnvVar" task was not found. Check the following: 1.) The name of the task in the project file is the same as the name of the task class. 2.) The task class is "public" and implements the Microsoft.Build.Framework.ITask interface. 3.) The task is correctly declared with in the project file, or in the *.tasks files located in the "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin" directory. WixSharp Setup1 C:\Users\jonre.nuget\packages\wixsharp\1.9.5\build\WixSharp.targets 5

Steps to reproduce:

1) Remove the nuget packages from a wixsharp project 2) Delete your obj directory 3) Re-add the nuget packages and choose the option PackageReferences instead of Packages.config 4) Attempt to build the project

settings2 settings1

jonreis commented 5 years ago

@oleg-shilo I solved this by: 1) Checking SetEnvVar.dll into source control 2) Added to my csproj file.

Could you let me know if this is the recommended approach?

Thank you!

oleg-shilo commented 5 years ago

Well, not exactly :o)

For quite some time SetEnvVar.dll was a part of the build but because it was causing some problems with packages updates it has been removed and now WixSharp package relying on no external resources.

If you have problems with SetEnvVar.dll then most likely you are using older VS templates. Updating WixSharp project templetes extension will solve this problem. However... I just found that NuGet restore does not recreate the project structure the way it supposed to.

I am changing theist issue to BUG and will investigate it.

oleg-shilo commented 5 years ago

After some further digging I found that NuGet package is still invoking SetEnvVar MSBuild target. Thus fixing templates will only solve part of the problem.

The packages have been fixed (v1.9.5.1) and published. This will solve the problem of installing package on a brand new plain .NET project.

The templates fix is yet to come.

jonreis commented 5 years ago

@oleg-shilo as always thank you very much for your amazing library and help using it!

oleg-shilo commented 5 years ago

The VS project templates extension has also been fixed updated (v1.8.0): https://marketplace.visualstudio.com/items?itemName=OlegShilo.WixSharpProjectTemplates

jonreis commented 5 years ago

Hi @oleg-shilo, I tried out the new templates (v1.8.0) and they are still using packages.config and placing dlls into the local project "packages" directory. However; if you use the new PackageReference mechanism the nuget packages get stored in the /.nuget folder.

It does seem to work for me if I use the PackageReference approach and only include (added by nuget automatically) in my csproj file.

    <PackageReference Include="WixSharp">
      <Version>1.9.5</Version>
    </PackageReference>

If I look in my obj directory there is a targets file that is automatically generated by Visual Studio. It contains:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
  </PropertyGroup>
  <ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
    <Import Project="$(NuGetPackageRoot)wixsharp.bin\1.9.5.1\build\WixSharp.bin.targets" Condition="Exists('$(NuGetPackageRoot)wixsharp.bin\1.9.5.1\build\WixSharp.bin.targets')" />
    <Import Project="$(NuGetPackageRoot)wixsharp\1.9.5.1\build\WixSharp.targets" Condition="Exists('$(NuGetPackageRoot)wixsharp\1.9.5.1\build\WixSharp.targets')" />
  </ImportGroup>
</Project>

So it appears that all the necessary targets are being pulled in and that I do not need to do anything in the csproj file. Is that correct?

To summarize, every things seems work without having to use the WixSharpProjectTemplates if you use the PackageReference approach. Are the templates for backward compatibility, or am I missing something? What is the minimum requirement in the csproj file for Wixsharp to function properly using the PackageReference approach?

jonreis commented 5 years ago

@oleg-shilo I think I must have closed this accidentally. Please see my comment above.

oleg-shilo commented 5 years ago

I think there is a bit of confusion about this issue. I need to explain....

The problem with *targets reference to SetEnvVar.dll was areal problem and it is solved now.

Having nuget references as a packages.config is not a problem even though referencing the global packages from the project file is indeed a more attractive approach.

The real problem is that having project-listed packages does not play well with project templates. Despite my all effort was not able to find a solution when the template would allow project-listed packages. Furthermore, having project-listed packages prevents templates from being integrated with VS2015.

However if one starts with the plain C# console app then he can add nuget packages either way, globally or per project (packages.config)

jonreis commented 5 years ago

Ok, thanks for the explanation. Everything is working fine for me so I will close the bug.

allknower commented 5 years ago

Hello @oleg-shilo, Can you explain, please, what is the right way to pass VS variables to wixsharp script now? I used SetEnvVar task before, but it was deleted from WixSharp package. I read comments in this issue and in https://github.com/oleg-shilo/wixsharp/issues/569 and, of course, I read wiki, but couldn't realize what should I do.

Thanks!

oleg-shilo commented 5 years ago

SetEnvVar was initially introduced to pass the location o the project folder. Though later it became apparent that it created more problems than bringing the benefits whan upgrading the package. Particularly because the location of the project folder may also be safely determined from the current dir during the build. That's why it was eventually deleted from the solution.

But if you want to pass any sort of information into the project you can still red envars that you may set in the pre-build project events.

But if you want a complete flexibility then you can install WixSharp.bin package instead of WixSharp. This way tere will be no MSBuild custom task and building msi will need to be triggered from the post-build event by running the $(TargetPath) executable. And when you do that you can always pass any app arguments.

smaudet commented 2 weeks ago

Hmm. I'm also trying to use SetEnvVars. @oleg-shilo Could you possibly furnish the commit where it was deleted?

My use case is different - I have multiple project configurations and I would like to access those. I can't seem to find this feature in wixsharp, this seems the closest. However, it doesn't seem to work... (could be an msbuild/dotnet mismatch).

All we have is the dll and the source file, with no way to build. Hard to debug...

EDIT:

I see commit 13bde13d2ae14d5b5ef804582591eca903eecea1 removed it from the .targets file, so the wiki is currently incorrect:

i.e. <SetEnvVar Values="ProjectName=$(ProjectName);ProjectDir=$(ProjectDir);SolutionName=$(SolutionName);SolutionDir=$(SolutionDir)"/> is gone.

So I would have to use a very old version of wixsharp to get this working at all, and I am on WixSharp_wix4 (2.1.5)... alright.

I tried using <PackageReference Include="MSBuild.SetEnvVariable" Version="1.0.0.3" GeneratePathProperty="true"/> instead however my run configuration discards the set environment variables, so I think I will do this a different way...

Sorry to necro, hopefully useful comments for someone in future!

oleg-shilo commented 2 weeks ago

MSBuild.SetEnvVariable is no longer used. Bot streams six4 and wix3 are relying on a completely reworked build process that uses project references (at least wix4).

If you are creating a new project use VS templates. If you are upgrading the project then create a new project from the template and update the project file manually

smaudet commented 2 weeks ago

Yes I ended up impling my own msbuild task, there was no way to pull build config settings from the csproj.

SetEnvVariable wasn't any good either as env vars are transient.

I used the VS templates but those provided no way to pull build information.

oleg-shilo commented 2 weeks ago

no way to pull build information.

Can you elaborate on that? Not sure what you are trying to achieve.

smaudet commented 2 weeks ago

There is various information available to the build system, most notably $(Configuration) (for msbuild), but also any and all build-related information such as package reference paths, etc. (e.g. for pulling/using nuget stuff).

So I have a different build and different packaging needs for e.g. Debug vs Release (perhaps not a common need, but one I want nonetheless).

$(ProjectDir) and $(SolutionDir) are also nice to be able to pass directly to the builder script, as project structure need not be identical (you may have multiple solutions in different directories, or projects in folders other than the main solution folder). So yes, you can determine currently executing directory and resolve relative paths however this is both error prone and inconvenient.

This "relative dir" approach however is insufficient for doing anything more complex with the build.

oleg-shilo commented 2 weeks ago

Currently the old SetEnvarVariable is replaced with the shell command in the project file:

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="cd .\&#xD;&#xA;set ide=true&#xD;&#xA;&quot;$(TargetPath)&quot;" />
  </Target>

image

You can extend this approach to do more, like passing the context for the build script:

image

And then:

static void Main(string[] args)
{
    var myArg = args.FirstOrDefault(x=>x.StartsWith("-myArg"))?.Split(':').Last();
smaudet commented 2 weeks ago

Ah, that's what that thing does. I have it commented out, it was causing build failures, and the unicode escapes don't make for easy reading.

I think I'll stick with my current task - I have it wrapping a json file so I get (some) type safety, and marshalling for free. Bonus, I know exactly what it ran with vs having to debug or dump it.

oleg-shilo commented 2 weeks ago

These two link can help to understand the build process:

https://github.com/oleg-shilo/wixsharp/wiki/VS2019-%E2%80%93-2022-Templates

image

smaudet commented 2 weeks ago

Hmm. I was going to say the reason it breaks is the first time you build the target doesn't exist, but I think its more complex than that... I'll try it again and see what's wrong with your template.

I do think clearer documentation could be helpful, too (such as removing the old invalid hint and updating with current supported process).

oleg-shilo commented 2 weeks ago

I do think clearer documentation could be helpful,..

I am happy to process any feedback. But I may need your help in understanding the gaps.

  1. Can you please provide the details on the "old invalid hint"?

  2. Another question. Where you (as a user) would expect the description of the current process to be? I placed it in the VS integration section. Do you think there is a better place for it? So it is easier found.

  3. And the last one. "the reason it breaks is the first time you build the target doesn't exist". I just retested it again and the fresh new project (from the VS template) builds right away. Is it some specific template that does not build on the first attempt? Or maybe it is something in the project content that triggered the problem in your environment? Can you elaborate on this?

smaudet commented 1 week ago
  1. https://github.com/oleg-shilo/wixsharp/wiki/Developer's-Guide

search for this paragraph:

You can also map VS project variables to environment variables by using custom MSBuild task SetEnvVar.dll distributed with Wix# NuGet packages. The following XML definition placed in WixSharp*.targets file will always map the VS project variables to the environment ones so your build script can access them:

  1. I'd expect it in the wiki, but I'd expect to be called out "how to pull build information" or some-such.

Your VS integration page is actually not very helpful, I found the templates without finding your page and created a project.

Then your page just looks like you're walking someone through how to use VS templates, which I suppose if you've never created a project before might be helpful, but its not what I'm looking for when I already have a working project that builds in Visual Studio (except for one weird bit of code that is a bit inscrutable).

I think the problem is you tried to make it too seamless and so when something breaks, its hidden inside weird-looking code buried at the bottom of a page that looks like it is not relevant. You show some images of setting command line parameters, but there's never any textual mention of what to do, so I never found it (especially by search).

  1. I retested as well. Works for me now. With my project that didn't work, it still fails if I re-enable (works fine without). I think it may have been an issue with code I modified and not expecting it to fail during build.

Which I think is the other part of this - that task should perhaps be disabled by default in the build scripts, rather than on and always running (IIRC I just wanted it to build and it failed). Then you can explicitly mention how to run the installer as part of the build by uncommenting the task.

$${\color{red}Even \space just \space a \space comment \space explaining \space what \space the \space task \space does \space in \space the \space template \space would \space have \space helped \space a \space lot...}$$

oleg-shilo commented 1 week ago

Thank you @smaudet. I have updated the documentation according to your feedback.

  1. I have completely removed the description of the obsolete build process and gave a brief description of the two-step build flow.

    1. I am not sure "how to pull build information" is an intuitive title so I simply covered this topic in this VS integration page at the end of the section.

that task should perhaps be disabled by default in the build scripts.....

Unfortunately, it's not that simple. Disabling the post-build event simply prevents msi from building. Thus the build script will be compiled but never executed. And the user feedback I received previously indicated the strong expectations of msi file being produced as the result of building the VS project. Particularly, if the project is part of the CI.