EXE file is not working - c#

I have a .msi (windows installer package) file into my project . I generated .exe file from .msi file successfully but whenever I try to open that .exe file or run as administrator it does nothing . How to solve this? Anything will help regarding this . Please help
UPDATE
Here is my code for .msi file
components.wxs
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<?include Defines.wxi?>
<Fragment>
<ComponentGroup Id="MenuComponents" Directory="ProductMenuFolder">
<Component Id="ProductMenuComponents" Guid="*">
<!--<Shortcut Id="UninstallPackage" Directory="ProductMenuFolder" Name="Uninstall package"
Target="[System64Folder]msiexec.exe" Arguments="/x {[ProductCode]}" Description="Uninstalls $(var.YourApplicationReference.TargetName)"/>-->
<RemoveFolder Id='ProductMenuFolder' On='uninstall' />
<RegistryValue Root='HKCU' Key='Software\[Manufacturer]\[ProductName]'
Type='string' Value='' KeyPath='yes' />
</Component>
</ComponentGroup>
<ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
<Component Id="FileWatcher">
<File Source="$(var.FileWatcher.TargetPath)" />
<!--Register this file as a Windows service-->
<ServiceInstall Id="ServiceInstaller"
Type="ownProcess"
Description="Sends Incoming mainframe files to the Webservice"
DisplayName="FileWatcher"
Vital="yes"
Start="auto"
ErrorControl="ignore"
Interactive="no"
Name="FileWatcher"
Account="[ACCOUNT]"
Password="[PASSWORD]">
<ServiceConfig Id="svcConfig" DelayedAutoStart="yes" OnInstall="yes" OnReinstall="yes" OnUninstall="no" />
</ServiceInstall>
<!--Set the user to be used by the service-->
<util:User Id="ServiceUser" Name="[ACCOUNT]" Password="[PASSWORD]" CreateUser="no" LogonAsService="yes" UpdateIfExists="yes" />
<!--Added example of how to stop service automatically-->
<ServiceControl Id="ServiceControl" Stop="both" Remove="uninstall" Name="FileWatcher" Wait="yes" />
</Component>
<Component Id="FileWatcher.Files" Guid="*">
<!--<Component Id="MAIDFileWatcher.Files" Guid="*">-->
<File Id="filB93E7D71690869B9CD2D0A479DB69C6C" Source="$(var.FileWatcher.TargetDir)\ExceptionHandling.dll" />
<File Id="fil487232F7A833919419AF9537A4390083" Source="$(var.FileWatcher.TargetDir)\ExceptionHandling.xml" />
<File Id="filDE3649B71309470D2D7C086E0FAABAE8" Source="$(var.FileWatcher.TargetDir)\itextsharp.dll" />
<File Id="filF73350F1AEF9ECF2621D4E63B9823029" Source="$(var.FileWatcher.TargetDir)\FileWatcher.exe.config" KeyPath='yes'/>
</Component>
</ComponentGroup>
product.wxs
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?include Version.wxi?>
<?include Defines.wxi?>
<Product Id="$(var.PRODUCTCODE)" Name="$(var.PRODUCTNAME)" Language="1033" Version="$(var.REVISION)" Manufacturer="$(var.MANUFACTURER)" UpgradeCode="$(var.UPGRADECODE)">
<Package InstallerVersion="400" Compressed="yes" InstallScope="perMachine" Comments="$(var.COMMENTS)" Description="$(var.DESCRIPTION)" />
<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Feature Id="ProductFeature" Title="$(var.PRODUCTNAME)" Level="1">
<ComponentGroupRef Id="ProductComponents" />
<ComponentGroupRef Id="MenuComponents"/>
</Feature>
<UIRef Id="USERUI" />
<?include Actions.wxi?>
</Product>
</Wix>

You can debug an msi installation with a command line like this:
msiexec /i someapplication.msi /L*vx log.txt
This will run the installer and output log info to a file called log.txt.
See also: Windows Installer Command Line Options

Another pro tip is to debug your installer in a virtual machine. Take a snapshot before installing so you can roll back, or repeat the installation after making code changes and start from a reproducible state. I can't imagine debugging installers without Hyper-V - it's essential to me.

This is basically just shooting from the hip, please ignore whatever is not relevant (maybe check the very last three bullet points first):
Best practice: first of all, you are installing multiple binaries with a single component. This is a violation of component creation best practice.
For something this small I would suggest you use one component per file. This solves all kinds of future problems with patching, upgrades and other things.
What happens if the component rules are broken? Please skim this, or take our word for it and just use one file per component. At least make a separate component for all binaries (required).
A little blurb about the nature and philosophy of component GUIDs: Change my component GUID in wix? Some find it helpful to understand the mysterious and always troublesome component GUIDs.
If you insist on using multiple files per component, make sure that the key file for the component is a versioned file. I would think WiX would auto-magic this.
If you don't have a versioned key file, you could risk the component not installing at all if there are files already in the target location.
If you do have a versioned key file, make sure that your install has a higher version binary than the one it may encounter on disk at the target location (if any). Please read about the MSI file versioning rules for an explanation.
Logging: Does your application have a log feature (by default, or one that you can enable) which you can use for debugging? Maybe to the system's event log? Wouldn't services write there?
Dependencies: Also, did you check the pointers I provided earlier with regards to dependency checking? C# Debug folder when copied to another location does not run the exe.
Checking first the modules view in Visual Studio, and then using Dependencies.exe to check for missing dependencies?
Using procmon.exe is a little involved, but almost always reveals surprises and problems that can be hard to detect in other ways: Registering a CPP dll into COM after installation using Wix Msi installer
Does Fuslogvw.exe tell you anything? (.NET assembly binding failures).
Service Credentials: are you sure that those login credentials are getting applied during installation?
Did you try to set them manually to see if the service will run then? Did you add these properties to the SecureCustomProperties list of properties allowed to pass to deferred installation mode?
I think WiX has "auto-magic" here and does this for you, I forget. Check SecureCustomProperties in the property table of your final, compiled MSI using an appropriate tool, for example Orca.
With that delayed service start setting, is the service even running? (got to mention it at least). Or did you say it crashes on launch?
Hard-coded references: pointers to missing resources.
Did you check all the manifest files and config files (FileWatcher.exe.config) for anything funky that points to resources on your developer box (erroneous, hard-coded references)?
Could there be lacking resource files? (images, dlls, etc...).
Architecture & runtime requirements: is the target computer the same architecture as your developer machine? Just to chalk it up, surely you would see a warning about this?
What is the CPU targeted by your code? Any CPU? Did you try to manually register the files on another machine (a clean virtual machine maybe).
Is there anything special about the problem, target computer? Does it have weird policies? Does it have security software blocking things? Does it lack a common runtime component that is installed on your development computer? (.NET, VC++ runtime, VC runtime, java, etc...). These are the things a procmon.exe session should reveal, or a check with Dependencies.exe should show.
Are you using the notorious FileSystemWatcher .NET class? I have used it only once many years ago, but it caused me a lot of grief and I had to stop using it. It did crash my service file regularly.
I will dig up some links here if you are using this class.
Found a couple for now: FileSystemWatcher events raising twice despite taking measures against it and FileSystemWatcher vs polling to watch for file changes.

When I have installed my EXE under %PROGRAMDATA% I had the same issue
When I have installed my EXE under %PROGRAMFILES% I solved the problem

Related

C# application user settings maintained during update

I have a C# application that currently stores user settings/configurations in a separate xml file. My application uses a wix installer and id like to know if there is a way to preserve the xml file should the user be installing a newer version of the application if they install without first removing the older version. The xml file is stored in the CommonAppData folder and should be removed if the application is uninstalled.
Backup question - Is there a better way of doing this than my current method?
UPDATE
I have implemented the following code:
<CustomAction Id="Cleanup_Files" Directory="CompanyFolder" ExeCommand="cmd /C RD
"[CommonFolder]" /s /q" Execute="deferred" Return="ignore" HideTarget="no"
Impersonate="no" />
<InstallExecuteSequence>
<Custom Action="Cleanup_Files" Before="RemoveFiles" >
Installed AND REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE
</Custom>
</InstallExecuteSequence>
This removes the CommonFolder directory as required on uninstall but it still removes the directory when upgrading. What changes are necessary to achieve this?
The easiest thing to do is: do not insatall this XML file by the setup, but instead let it create by the application if it is not there. By this, an update will not touch the file.
With this scenario it is also possible to migrate the settings from an older (or newer) version.
However, the file will also remain on uninstall. If it is a requirement to remove it in this case, you can do this by a custom action with a condition like Installed AND REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE
The solution for me was to follow the advice of Klaus but with some additional changes to my product.wxs file. I had to add 'AllowSameVersionUpgrades="yes"' to the MajorUpgrade section.
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A newer version of
[ProductName] is already installed." />
Thanks to Klaus for all of their advice!

hyphen in DLL name for VS reference

First, some background. I'm working on an application that uses the WiX Toolset to create the installer. We frequently use WiX to control setting up our client's directories and place the needed DLLs where they need to go.
Now, on to the problem: I added a new DLL to my application, lets call it "NewCode.dll." NewCode.DLL has a dependency on "Dependency-1.DLL." So in order to make my program work, I need to also include Dependency-1.DLL in the installer. And this is where I get stuck. Because of the "-1" in the name of Dependency-1.DLL, Visual Studio doesn't seem to allow me to add it as a reference to the project. Without adding it as a reference, I don't believe WiX can find it, and so NewCode.DLL will fail at run time. Simply removing the hyphen is not an option because NewCode.DLL won't be able to reference Dependency-1.DLL anymore.
I have verified that if I manually place the Dependency-1.DLL into the required folder, everything will start working. So I suppose doing some "batch file post-build-action magic" to copy files around is a valid option, but its not ideal. I'd really prefer to continue to rely on the WiX Toolset.
Working answer:
The accepted solution did fix my problem. But I thought I'd add on to my post in case anyone else falls into the same trap I did. The first DLL is a direct reference, while the second is a transitive reference that the first depends on. I set the default location for the component group for where to look for the DLLs to be the TargetDir. With my old set up, this was assuming that VS would handle copying the DLL to the TargetDir for me via "Copy Local = true". Now, however, if you look at the second DLL that I'm adding, I set the source explicitly and WiX is moving the DLL for me.
Since WiX moves the DLL for me now, this gets me around the issue of VS not allowing the hyphenated DLL name as a reference.
<ComponentGroup Id="AForge" Directory="INSTALL_ROOT" Source="$(var.Pslf.TargetDir)">
<Component Guid="{FA5BEE4F-0D54-4B76-BAEF-DC8E31F6605F}">
<File Name="AForge.Video.FFMPEG.dll" KeyPath="yes"/>
</Component>
<Component Guid="{1FB3EFEA-1BF3-4416-8AE3-026F2E4EECFC}">
<File Name="avcodec-53.dll" KeyPath="yes" Source="$(var.SolutionDir)pslf\lib\AForge\avcodec-53.dll"/>
</Component>
</ComponentGroup>
You don't need a WiX reference to pre-built DLLs. Just put the direct path to it in the Source attribute:
<File Id="file_Dependency_1.DLL" Name="Dependency-1.DLL" KeyPath="yes"
DiskId="1" Source="$(var.SolutionDir)path\to\dlls\Dependency-1.DLL" />

Trying to read a file and then write a file during a WiX install in a CustomAction

I am having a tough time with this. There are a lot of SO articles about these settings but I'm still stuck.
My goal is to perform two steps:
Read a file that will be physically shipped with the msi. In other words, there will be three files setup.exe, test.msi, specialFile.txt
During the install, I want to create a new file in the install path. C:\Program Files\MyCompany\MyApplication\newFile.txt
The file in step 2 is created by reading something out of specialFile.txt from step 1.
My problem is navigating the murky combinations of WiX settings to enable me to read session variables and have high enough privs to write the file out. This has not been easy.
Here is what I've been doing:
<Binary Id="MyCustomAction.CA.dll" SourceFile="path\to\MyCustomAction.CA.dll" />
<CustomAction Id="MyActionsName"
Return="check"
Execute="deferred"
BinaryKey="MyCustomAction.CA.dll"
DllEntry="MyCustomAction"
Impersonate="no"/>
<CustomAction Id="CustomAction1"
Property="LookupUnattendedXML"
Value="INSTALLFOLDER=[I_Can_Get_This_From_The_Directory_Tags];SOURCEDIR=How_To_Get_This???"/>
<InstallExecuteSequence>
<Custom Action="CustomAction1" Before="MyActionsName" />
<Custom Action="MyActionsName" Before="InstallFinalize">NOT Installed AND NOT PATCH</Custom>
</InstallExecuteSequence>
impersonate="no" in order to have enough privs to write the file
Execute is "deferred" in order to have enough privs to write the file (I don't understand how this works)
The Custom tag is set to Before="InstallFinalize". I tried other settings for this. Before="InstallFinalize" seems to fire after the files have been installed.
Then in the C# code, I appear to need to access session to get what I need. I ask for session["sourceDir"] to figure out where the .msi was launched from and then search for specialFile.txt This won't work with "deferred" turned on. I also access a Directory ID called INSTALLFOLDER which is supposed to refer to the path where the application is installed. It appears to do that. session["INSTALLFOLDER"]
The last wrinkle is that when I execute the .msi directly (no bootstrapper) and with deferred changed to immediate, I am able to read the session["sourceDir"] and it's really the location of the .msi as I wanted. When I use the setup.exe bootstrapper, this same variable points to an internal System directory where it appears that the MSI was copied to. I would like to let the user have both methods of execution (with and without the setup.exe bootstrapper) and somehow be able to access these paths.
UPDATE:
This article and this article about custom properties in deferred actions have enabled me to read the install folder in the custom action (now I know where to write the file to). A remaining challenge is figuring out the location of the MSI so I can read the file without using session["SourceDir"] because the Custom Action is deferred.
This would have solved the issue:
<Binary Id="MyCustomAction.CA.dll" SourceFile="path\to\MyCustomAction.CA.dll" />
<CustomAction Id="MyActionsName"
Return="check"
Execute="deferred"
BinaryKey="MyCustomAction.CA.dll"
DllEntry="MyCustomAction"
Impersonate="no"/>
<CustomAction Id="MyActionsName.CustomActionData"
Property="MyActionsName" <!-- this is important -->
Value="INSTALLFOLDER=[I_Can_Get_This_From_The_Directory_Tags];SOURCEDIR=[SOURCEDIR];ORIGINALDATABASE=[OriginalDatabase]"/>
<InstallExecuteSequence>
<Custom Action="MyActionsName.CustomActionData" Before="MyActionsName" />
<Custom Action="MyActionsName" Before="InstallFinalize">NOT Installed AND NOT PATCH</Custom>
</InstallExecuteSequence>
In the custom action you can access the data set in MyActionsName.CustomActionData via session.CustomActionData["propertyname"]
In general you have to pass each variable/property you want to use of the 'normal' installation explicitly to the deferred custom action to show up in CustomActionData.
I've just seen that I'm very late. But maybe someone else will find this helpful.

Why is ClickOnce downloading unchanged files?

Context:
I'm using C# and Visual Studio 2015 to develop and deploy an application with ClickOnce, and I'm trying to shrink the ClickOnce update download size. ClickOnce is capable of delta-only updates:
When updating an application, ClickOnce compares the hash signatures of the files specified in the application manifest for the current application against the new version. If different, ClickOnce downloads the new version. If the signatures match, ClickOnce copies the existing file and uses it in the new version of the application. This approach prevents ClickOnce from having to download the entire application again, even if only one or two files have changed.
Problem:
I've verified that between updates of MyApp, the hash signatures of most files do not change (on the command line using shasum or in the actual manifest files). But ClickOnce still downloads every file on every update.
For instance, MyApp depends upon Emgu.CV.dll, and I just published MyApp 1.0.9.4 from within Visual Studio 2015. Here is the Emgu.CV.dll reference from the manifest file located in the publish output location, MyApp\Application Files\MyApp_1_0_9_4\MyApp.exe.manifest:
<dependentAssembly dependencyType="install" allowDelayedBinding="true" codebase="Emgu.CV.dll" size="363520">
<assemblyIdentity name="Emgu.CV" version="3.0.0.2158" publicKeyToken="7281126722AB4438" language="neutral" processorArchitecture="msil" />
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
<dsig:DigestValue>lUb/oa0aQL6HWEhY8Juj6Mc1wChKo0owhJJ+sSfqZUs=</dsig:DigestValue>
</hash>
</dependentAssembly>
And here is the same .dll's dependency tag from a previous deployment, MyApp_1_0_9_2\MyApp.exe.manifest:
<dependentAssembly dependencyType="install" allowDelayedBinding="true" codebase="Emgu.CV.dll" size="363520">
<assemblyIdentity name="Emgu.CV" version="3.0.0.2158" publicKeyToken="7281126722AB4438" language="neutral" processorArchitecture="msil" />
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
<dsig:DigestValue>lUb/oa0aQL6HWEhY8Juj6Mc1wChKo0owhJJ+sSfqZUs=</dsig:DigestValue>
</hash>
</dependentAssembly>
They are identical. Notably, the <hash><dsig:DigestValue> content is identical, just like all of the other ~150MB worth of dependencies declared in their respective tags between versions 1.0.9.2 and 1.0.9.4.
Only a couple of hash values actually changed between those two manifest files. For example, the MyApp.exe hash changed from
JryzNpD+emqeruXW7X2unRm0i58w9z9ct++Jeog40FI=
to
tF/hs87T4n9sMgoUJUmk31zAUsi7MsWXhLdKGxlR+EM=
But a ClickOnce update from 1.0.9.2 to 1.0.9.4 downloaded MyApp.exe and Emgu.CV.dll and every other file, changed or not!
Why is ClickOnce downloading files whose hash hasn't changed?
Research so far:
This SO question is related, but the answer isn't applicable because I'm not rebuilding the assemblies that are being redundantly downloaded, they're just being copied (as is evident from the unchanging hash signatures).
This SO question is related, but the asker simply misunderstood what "Copy if Newer" meant.
I've read this troubleshooting MSDN page, my problem doesn't appear.
The issue is the ClickOnce progress dialog. It always shows the whole size of your application, even it only a single file is downloaded. Make sure to run a monitoring tool like Fiddler to see what actually is being transferred.

GlobalAssemblyInfo.cs and strong naming

I have a GlobalAssemblyInfo.cs file in the root of my solution, and I have something like the following entry in it to enable strong naming of my output assemblies.
#pragma warning disable 1699
[assembly : AssemblyKeyFile("..\\keyfile.snk")]
#pragma warning restore 1699
This approach has two drawbacks. Firstly, AssemblyKeyFileAttribute is deprecated, and so to avoid compilation warnings I need the pragma lines you see above. Secondly, I either need to keep all my projects at the same depth relative to the root to use the relative path, or use an absolute path, which dictates a checkout location on other users' machines (and on continuous integration servers/build agents).
Does anyone have a better solution than this, other than going through each project setting strong naming in the project file?
Well, to avoid the path problem you can use [assembly:AssemblyKeyName(...)] instead (although IIRC this is also deprecated); use sn -i to install a named key. Each machine (that does builds) would need this key adding.
Other than that; yes, you'd probably need to edit the project files.
Those attributes for key signing were deprecated for good reason (information leakage), which is another reason to go the project route.
If you have a lot of projects it might be possible to set them via a recorded macro, or even directly manipulating the .csproj files (ensure they are unloaded from VS first).
Richard makes a good point about information leakage - I've now found posts from Microsoft's .NET team where they describe this. So I've gone for his suggestion and come up with the following NAnt target:
<target name="strongName" description="Strong names the output DLLs">
<foreach item="File" property="filename">
<in>
<items>
<include name="**/*.csproj"></include>
<exclude name="**/*.Test.csproj"></include>
</items>
</in>
<do>
<echo message="${filename}" />
<xmlpoke file="${filename}" xpath="/m:Project/m:PropertyGroup/m:SignAssembly" value="false">
<namespaces>
<namespace prefix="m" uri="http://schemas.microsoft.com/developer/msbuild/2003" />
</namespaces>
</xmlpoke>
<xmlpoke file="${filename}" xpath="/m:Project/m:PropertyGroup/m:AssemblyOriginatorKeyFile" value="..\keyfile.snk">
<namespaces>
<namespace prefix="m" uri="http://schemas.microsoft.com/developer/msbuild/2003" />
</namespaces>
</xmlpoke>
</do>
</foreach>
</target>
The <namespaces> element is necessary for the XPath to be resolved in the csproj file - note that this is for VS2008, and something slightly different may be needed in VS2005.

Categories

Resources