2

I have a custom action to do a http post to send to google analytics for tracking installs. My custom action does other things and those are working. So I know my custom action is being called. I'm using HttpClient which requires a reference to System.Net.Http. I think the problem is with the reference. Is there something special i have to do in order to make sure the reference can be found?

I tested the code in a separate project to make sure the code works, and it does. When I try to run the msi it just fails to install. I put the whole http post inside a try statement to get by this, so at least the install doesn't fail.

Anyone got any ideas on what it could be or what to check?

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
JED
  • 55
  • 8
  • This question is unanswerable because you don't provide any context of how/where this custom action is scheduled and you don't provide any indication that you've attempted to look at log files or debug the problem. You should remove the try..catch or place a session.Log(ex.Message) inside the catch and log the MSI to read what error is occurring. – Christopher Painter Apr 22 '18 at 15:05

2 Answers2

1

UPDATED COMMENTS: In order to address the downvotes: accessing the Internet in your MSI setup is not advisable due to the overall nature of the MSI technology. It is an old technology not designed for the Internet age. It was designed to install Microsoft Office way back in the 90s (though there are rumors that the Windows Store might allow MSI files to be downloaded now in 2021).

Even accessing the local network from custom actions is difficult due to impersonation as SYSTEM when running in deferred mode (custom actions with admin access to system).

The normal situation is that SYSTEM context can access the network via the machine account only. See mind map of this - the map is based on this SO answer.

Proxy servers, firewalls, security software and other mechanisms can interfere with non-system context custom actions trying to access the Internet. There could also be no user logged on when the package is deployed silently.

Just write a flag to the registry and have the application report the fresh install or update on application launch instead?

Note on proxy servers: a proxy server for Internet access means the machine does not have direct Internet access, but must access the Internet via a machine dedicated as a "gateway". Back in the day I used to "discover" the proxy settings by reading IE settings, but overall: don't assume direct Internet access is available.


For reliability reasons setups should not do complicated things such as this. Can you do this from within your application instead? Then you will be in a more predictable impersonation context with full Internet access and with user interactivity - if needed. Much more reliable, easier to debug and you have interactivity with the user to sort out connection problems. And you can try again many times, if it fails at first. A setup is "one shot" in comparison - and much harder to debug.

Keep in mind that most corporate deployment is done in silent installation mode. When a setup runs in silent mode, you have to suppress all such fancy features that may require Internet access or interactivity of some sort. Accessing the Internet from a setup is an anti-pattern - at least for now - future online deployment techniques could change this truth. However, during a silent, corporate install your setup will likely run in system context with no Internet access at all (the SYSTEM account can not access the Internet - unless the network setup is crazy). You could also cause crashes trying to connect and triggering an exception, and you could trigger security software interference as well - it happens for "unusual setup behavior".

Even if a user runs your setup with a proper user context, there might be a proxy server that you have to access the web with - and then your connection will still fail unless you retrieve proxy settings from the system. I have never done that in a setup - again, since setups should not require Internet access in my opinion.

Keep in mind that the .NET framework is still not available in all "common versions" on all OS versions.

Hope that made sense to you. Please put this feature in your application. Tag the registry once the operation has run - if it should run only once. You can even write to HKLM if you open up some ACLs there to allow anyone to write the flag.


UPDATE: shortened summary. Doing this in your setup will fail if:

  1. .NET framework is missing, disabled or wrong version
    • Less and less of an issue, but still missing here and there
  2. Internet proxy is required for Internet access
  3. Deferred mode CA (for read/write system access) is used (allows no Internet access)
  4. Silent installation via distribution system (should allow no Internet access)
  5. Interactive, silent installation (most likely fails, depends)
  6. There could be interference from security software (unusual setup activity).
    • Anti-virus / malware protection
    • Firewall (blocking msiexec.exe)
  7. GUI requirements? Did you try running component from a console application?
Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
  • okay. it was just a thought i already had google analytics in the application for tracking different features and thought it would be cool to get the number of installs. I was going to put it all in a try statement for the cases of it being included in a build. ill just table it and move in. really loving wix and how easy it is to make custom msi for free. – JED Apr 21 '18 at 02:25
  • When your application runs it has generally been installed? You could "tag" it to indicate whether it has been deployed with a package or somehow assembled manually (build output). Would that give you the number you seek? In the future such setup-network activity that you describe could become more common - but for now I'd say it isn't worth your effort - it is very error prone as stated above. – Stein Åsmul Apr 21 '18 at 02:34
  • Yes WiX can be really cool once set up. I assume you build your custom action with Visual Studio / Votive so you apply the `MakeSfxCA.exe` as part of the build to create a native wrapper dll? (just do a build and check the end of the build log if this is not clear). – Stein Åsmul Apr 21 '18 at 02:38
  • I haven't used this much, but right clicking your references in Visual Studio and going properties and then set copy local to true should include your dependent framework file in your wrapper dll? Maybe there was something else missing. – Stein Åsmul Apr 21 '18 at 02:49
  • I was going to ask you Chris if the latter comment on copying the built-in .NET file to the native DLL would be wrong advice, which I think it is (the file is a runtime file available in .NET runtime). However, I stand by the advice to not include features like this in the setup - it is simply not reliable. Why do this in the setup when it is better done in the application? (debugability, repeatable, interactive error messages, no impersonation problems, etc...). – Stein Åsmul Apr 22 '18 at 15:26
  • This is not an answer to why it is not working for the person asking the question. Are there any WiX documentation references that explicitly mentioning blocking network in the bootstrapper? I also found out that custom .NET bootstrappers are prevented from accessing the filesystem as well. – Wouter Jun 03 '21 at 10:36
0
  1. Log your MSI.

  2. Provide logging in your custom action. MSI has no idea what it's doing so you need to log, log, log.

  3. Read the MSI log.

I don't suspect missing .NET because the try catch would have made no difference as the CLR would have never fired up. I suspect you'll find your getting an error out of the HttpClient indicating that the remote host can't be connected.

It likely it is proxy related. Internet connectivity isn't universally unavailable in any installer context (How else would web download and web download silent installers work???? ) but it's also not a sure thing. Every customer / site / machine can be different so you may or may not be able to get through.

I would treat this type of interaction as "best effort". First try it in immediate context (to possibly run as the impersonated launching user and get their proxy access ) and if that doesn't work try to run as deferred context to run as SYSTEM and see if it has access. Either way try|catch|log the error and move on. Don't block the install over this.

Christopher Painter
  • 54,556
  • 6
  • 63
  • 100
  • "*Every customer / site / machine can be different so you may or may not be able to get through*" - you summarized why I conclude that this approach will never be reliable. Why fight with the unknown? Get your stuff installed and then do dynamic stuff in a loggable / interactive context. In the future we might get to a state when Internet access is taken for granted, but MSI was never designed with that as a primary goal. – Stein Åsmul Apr 22 '18 at 15:29
  • "Best Effort" You make an attempt to capture the metric you are looking for and you move on if you can't. No harm, no foul. You can have the exact same problem at run time also. Again, best effort no harm no foul. People want to capture user experience today and they are asking for runtime experience and they are asking for deployment experience. FWIW, WiX itself phone homes during the install. You can see it in Fiddler or you can look through the sources. So does the .NET framework install itself. – Christopher Painter Apr 22 '18 at 15:45
  • Besides, your argument doesn't even answer the question. Your just debating an opinion that wasn't even asked by the OP or by me. I'm just explaining how to solve the problem which in fact was the question. – Christopher Painter Apr 22 '18 at 15:52
  • The OP accepted my answer. I think the problem was "solved" by focusing on his intent and overall need - rather than technical issues per-se. It is obviously fine for me if he decides to accept your answer instead. – Stein Åsmul Apr 22 '18 at 16:20