ClickOnce not replacing App_Data files during re-install - c#

I noticed a behavior I don't understand happening with my application's ClickOnce deployment: a database file (Main.accdb) that is marked as a data file isn't replaced in C:\Users\username\AppData\Roaming\AppName after re-installing or installing a newer version.
In the Project Properties > Publish > Application Files I have:
File Name App_Data\Main.accdb
Publish Status = Data File
Download Group = (Required)
Hash = Include
In the file properties I have:
Build Action = Content
Copy to Output Directory = Copy always
When I install my WPF application using ClickOnce the first time, the file is found in C:\Users\username\AppData\Roaming\AppName. However, if I uninstall, delete the file in that folder, and re-install it is not replaced. In fact, anything removed from that folder isn't replaced by re-installation.
I tried various options for the Publish Status but the same behavior happens regardless of which options I choose. I'm using WPF with C# in Visual Studio 2017.
Why is this happening and how can I make it so that the file is always there when the application installs (or even better, launches)?

It turns out that the App_Data folder behaves differently and the issue can be resolved by using a folder with any name except App_Data.
I can't find this documented anywhere except for a handful of forum posts of users with similar issues, however, I was able to verify that it all works exactly as expected once I changed the folder name.
All that being said, Microsoft does seem to want developers to use App_Data for databases, so perhaps this is an exception to the norm and may not be the right approach for most projects. In my case, it's a desktop application that needs to deploy a local Access database to the user's computer on install and keep it up to date/replaced during re-install and updates.

Related

ClickOnce overwriting .exe.config with old version from 'obj' directory during publish

I'm working on an old ClickOnce app that's being updated for the first time in a couple of years.
As the title states, for some reason the ClickOnce publish is overwriting the generated ApplicationName.exe.config file with an out of date version located in the \obj\ subdirectory of the project.
This is causing a couple of issues:
Firstly, the hash fails on that file when trying to install the ClickOnce. My assumption is that Visual Studio is generating the .exe.config file as usual and generating a hash for the generated version, but then copying this other version over the top thus breaking the hash (there are no pre or post build events in the project).
Secondly, even if I disable hashing on that file, any changes I make to app.config don't make it to the published version as the config is overwritten by this old \obj\ version. If I delete the file from the \obj\ folder, when trying to run the ClickOnce setup it tells me it's missing the file and aborts.
I've done a text content search of the entire project directory and can't find any mention of this \obj\ file anywhere, but it has to be there because the bug is reproducible on a different PC that's pulled the project via source control.
I'm baffled because I thought that the \obj\ folder was just used for VS's local working files, and I can't understand why, how or where in the config files something like this could be set. Help!
Edit: Other stuff that's been tried:
Cleaning the project
Publishing to a fresh location in ClickOnce
Wiping the \obj\ directory (except this one config file)

Azure Web Deploy publishing old version of MVC sites .dll

I deploy my MVC site via a web publish within VS 2013 to an Azure location. I have published many times without issue from the same machine and IP address, but yesterday it stopped working.
The publish is placing an old version of my projects .dll in the bin folder on the site. This version no longer exists on my machine, it isn't the projects current Git state (and has never been the current Git state) and is not the version in my Release, Debug or Demo compiled folder. I don't know where it's coming from.
So when I publish, I get errors relating to the database changes because the model behind my context has changed since this old version.
So currently when I publish I have to FTP into my site and replace the WebPortal.dll file with the one in my machines bin folder, and the the site works fine.
What could be causing it to revert to this old .dll and where is it coming from? Have I somehow excluded my changes past a certain point from the publish?
Note - My views are publishing absolutely fine, it is just the .dll that should contain the current compilation of Models, Controllers etc., but instead contains an old version missing loads of stuff.
JK
There might be an old version of your dll on the server that is not being overwritten during publish. Have you tried checking "Remove additional files at destination" the the settings section of the Publish dialog. That should remove all the files from your target location except the one you publish.
If you are still having a problem after that try publishing to your local file system so you can see exactly what publish is sending to your server.
Update:
Steps to publish web application to file system.
right click on your project in the solution explorer menu and select Publish.
In the profile section of the Publish Web menu select Custom publish type, click next.
Select file system in the Publish method drop-down. You should see the target location text box where you can specify your folder.
Continue with the rest of the publish steps with you usual settings and click publish.
Double check that your Build (Menu) > Configuration Manager > Build Configuration for Release has the tick next to Build for the WebPortal.DLL. If it isn't set to build then it would use an older version.
I had the same problem. Goodness knows where the old dll is coming from but in the end I up-versioned the library to a higher number and it seemed to cure it. I suspect the GAC or temporary files might be part of the problem although I can't find my library there.

Defining where files are installed

I am trying to deploy a .NET application as a ClickOnce Application, but I am having trouble defining where the application is installed. I need to know this because I have to include support files. I have already added the support files as "existing items". I had assumed that the program would install in Program Files, but it does not exist there. Instead, there is just a shortcut on the desktop. Can someone explain how/where the install path is defined using VS2012?
One solution I found was to use some of the Application class properties to determine where ClicOnce installed an instance of my program. But be aware that some those are deleted on uninstall of the program.
// To get the path for the executable file that started the application, not including the executable name.
PATH_RESOURCES = Application.StartupPath ;
For persistant data I created references to specific paths like :
PATH_USERDATA = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\myAppName\";
if (!System.IO.Directory.Exists((string)PATH_USERDATA))
{
System.IO.Directory.CreateDirectory((string)PATH_USERDATA);
}
PATH_REPORTS = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + #"\myAppName\";
if (!System.IO.Directory.Exists((string)PATH_REPORTS ))
{
System.IO.Directory.CreateDirectory((string)PATH_REPORTS );
}
Clickonce application gets installed under the user profile, not the Program Files path.
On windows Vista and Windows 7, clickonce application path will be somewhere in c:\users\username\AppData\Local\Apps\2.0\
On Windows XP, clickonce application path will be somewhere in c:\document and Settings\username\LocalSettings\Apps\2.0\
Note that Clickonce application path is different everytime upon installation, I found the best way is to make your app to write its own app path to the reg key, this way you know exactly where the app path is by looking at the reg.
So as user831062 pointed out, ClickOnce apps get installed under the user profile, not the Program Files path. Because of this, the install directory is different on every machine and almost impossible to access directly.
The part that I was hung-up on, was where are the files that I have included in the project located, and more importantly - how do I access them?
Well, as mentioned IN THIS LINK, if you mark the file as a "data file", under:
Project Properties > Publish > Application Files > Publish Status
you'll be able to access them using something like:
textBox = File.ReadAllLines(ApplicationDeployment.CurrentDeployment.DataDirectory + #"\myFile.txt")).ToList();
If you don't mark it as a "data file", but rather as just an "Include (Auto)", it will just be located in the install directory itself, which can be accessed by calling the file directly using something like:
textBox = File.ReadAllLines(#"myFile.txt")).ToList();
Anyway, took me an hour or so to find this, so hopefully it helps someone else out.
If you have added your files to your project, set the property for "build action" to "content" and set "copy to output directory" to "copy always". This way, the files will be included in your deployment. When the application is run, retrieve the location of the assembly and look in the same relative folder as where they were included in the project. For example, if they are in the top folder of the build output directory (/bin/debug/ or /bin/release/), they will be included in the same folder as the executable, which you can discover using this:
System.Reflection.Assembly.GetExecutingAssembly().Location

Visual Studio Moving a Content File on Publish

I'm developing a Web application that uses a couple XML files to store data. I have their Build Action set to Content, and on install the files are copied successfully to the Applications Virtual Directory:
C:\inetpub\wwwroot\ApplicationName\
The problem I'm having is that writing to these XML files (in order to save settings and things like that) causes a lot of write permissions issues. Therefore to get around it, I'm trying to copy these files from the virtual directory they're installed to to a new directory under the C drive, using the following PostBuildEvent in the Web Deployment Project:
xcopy "$(TargetDir)*.xml" "C:\CompanyName\ApplicationName\" /y
However, this does nothing. I'm not sure if this is because PostBuildEvents in the installer are not actually fired on install, but only on building the installer, or if TargetDir represents the bin directory:
C:\inetpub\wwwroot\ApplicationName\bin\
instead of the root application virtual directory:
C:\inetpub\wwwroot\ApplicationName\
Does anyone have any ideas? Has anyone dealt with this sort of thing before? I'm really stumped on this one.
Update:
I included a PostBuildEvent that should give full permissions to all users:
icacls "$(TargetDir)" /grant Users:F
But it doesn't seem to have resolved the problem.
I'm also unsure where exactly $(TargetDir) if pointing to, if it would be ..\ApplicationName\ or ..\ApplicationName\bin\
All you have to do is give full permissions to the user under whose context the Web Application Pool runs.
You can find this user by starting IIS manager and look at the Application Pools and Identity column
Something like
cacls C:\inetpub\wwwroot\ApplicationName /G Users:F
will give all permissions to this subdirectory to all users on the computer, If you are running under ApplicationPoolIndentity refer here
Turns out there's a much easier way to do what I was trying to do.
Instead of using PostBuildEvents to create a new directory structure and move files there, I added the new directory structure into
InstallerProject > View > File System
after which I located the Content Files from SomeProject entry in my installer project, and changed the Folder value to the newly specified directory structure, in this case
C:\CompanyName\ApplicationName\
This seems to work fine, I'm now able to access these files freely as I originally intended.

Clickonce and postbackevent

I have a WPF project and a post build event which copy files from a folder outside of the solution into the output directory.
I want to publish my application with Clickonce publish. The only problem is that the copied files are not included in the publish or the manifest.
I tried using MageUI.exe , msbuild /target:publish from the visual studio cmd and even tried to change the project file by hand including a beforepublishevent but none of that worked.
I am open to suggestions, but what I want is to take the output folder and make the installer install the output files. (e.g. install the .net 4 framework and visual c++ runtime libs)
If you don't want them in the solution, but you do want them in ClickOnce then the only possibility is to use an external tool to create the ClickOnce manifests as you can't add non-project files to the ClickOnce output in Visual Studio.
There are two options I know of:
Use MageUI to manage your ClickOnce manifests. You can add additional files to your application in Mage.
You could use some software that I created and sell called ClickOnceMore (www.clickoncemore.net). ClickOnceMore will allow you to add all the files in one directory to your ClickOnce manifests by adding a single folder include. You can also then control which sub folder on the client they get deployed to. It was designed to make scenarios like this simple. You can download a free trial on the web site.
I hope it helps. Apologies for the marketing plug, but I do think ClickOnceMore can solve your problem perfectly.
Instead of copying the files through a post-build event, why don't you include them inside the project, and mark Copy to Output Directory = Copy if Newer?
If they are DLLs, you can add them as reference instead.
There are other options to create installers such as WiX+SharpSetup. It's much more flexible, but also more complicated, and takes more time to create simple installers.

Categories