How to version control multiple forms in one application - c#

I have a single solution which contains 3 forms so far(will be more in the future).
The first form(main one) is a simple drop down list which shows available applications and opens selected form.
Now, I need to notify a user(on start up of the application) that there is a newer version of specific form available and therefore they should download an updated exe from the LAN.
I could check a folder where all exe files are kept and use exe name but this would only be applicable to the main form.
Any ideas?

You could:
Maintain each form in a separate class library meaning you can check
for updated .dll files rather than the exe.
Publish a text/xml/whatever file with information on the latest
published versions.
Just have an assumption that if either of the forms are updated, a
new exe is required anyway.

I would use an external XML file or SQL tables to store the applications that can be opened from the main form and their latest (assembly) version number
You could then use a local (user) settings file in the application to pair each application with the last known version and check this against your external file to determine if an update is required.
Then you just need to make sure you change your assembly version number and update your external file whenever you make changes.

Related

Correct way to implement auto-update for Android app built with Xamarin.Forms

I recently started building my mobile application using cross-platform Xamarin.Forms toolkit and I'm having a hard time trying to implement some sort of an auto-update mechanism for it.
More particularly, my app has some XML files along with images stored in assets folder, all packed up in the apk file, published to the Google Play.
What I want is to edit and update those xml and assets without publishing a new version of apk in the play store. But I also know that once packed into an apk, these resources cannot be changed unless the user manually downloads and updates the app via the store.
So I currently use the following work around:
I put all of the stuff like XML files or images that I want to update on my server then make an API for specifying their version as well as providing downloadable items.
Inside my app, I have a value representing the current version of the assets. Whenever the app starts, a background process will call the server's API and check if this version value matches the one on the server.
If the versions to not match, the service will automatically download the stuff from the server and store inside user device's internal storage.
Then the app will replace local resources with the resources from the server.
The problem is that this work-around of mine is too clumsy and hard to implement. Any ideas that can help me with a cleaner or more proper solution?
Your logic is correct... if you are "versioning" assets outside of the APK, you need to track a "version" of the local assets vs. the server|remote-based assets and download/cache new assets when the remote assets are newer...
You could use APK expansion (*.obb) files to bundle your "assets" separate from your .apk bundle. But anytime you need to change an .obb (even if it is a patch-based .obb) the application version has to change and thus you have to upload an .apk with a new version to the store even if nothing else in it has changed.
re: APK Expansion Files
The new .aab format (the .apk replacement) allows you to modify individual components of the application and thus the user get a true delta of the differences of what they have installed vs. the new changes resulting in very small update sizes. Again like an .obb, the app's version needs to change and thus a new .aab has to be uploaded.
Note: Xamarin does not currently support direct building of .aab bundles (like Android Studio does), but they can be "handmade" from the MSBuild artifacts.
re: Android App Bundles
Personally for scenarios like yours, I just use a single versioned .zip that includes all the files that can dynamically change between application level version|releases and thus only track that single file (unzipping into local app cache upon download). An version file (or just a file-hash) on the server contains the latest version and URL of the zip file and the zip file itself contains a matching version file. No cached files, download and unzip the file. Upon app update check, compare the version file in the cache to the server version and download/unzip if needed. (Note: I do not even use a separate "semantic version", I just use the SH1 hash of the zip file).

How to update the assemblies and file using setup project?

I've created a windows application in C#. The application has check for update feature. Whenever an update to the application is available, it downloads the setup file.
When we run the new setup it is successfully installed and we can see the new version in control panel. But the problem is that the assembly files and other files in installation directory are not updated. They are still the previous version of files.
I have set the following properties of the installer project:
- DetectNewInstalledVersion : true
- RemovePreviousVersion: true
Am I missing any property of setup project or is there any other approach to do that. I don't want to use any third party tool for setup creation.
You must increment the file versions of those files that need replacing. That's because of the Windows Installer file replacement rules.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa367835(v=vs.85).aspx

Winforms showing different values from xml

I have a windows service project which contains a Test.xml file. In the properies it is changed to copy always.
I have created a setup for service and after installing the service the Test.xml is present in the C:\program files(86)\service folder.
Now I want to edit the Test.xml file throgh a UI. So i have created a small Winforms project 'EditXml'. The EditXml is accessing the Test.xml like this
document = XDocument.Load(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Test.xml"));
I have added the EditXml.exe also to the setup of services. So after installing the service the EditXml.exe is also present in the folder.
But when I edit using EditXml I cant see the changes in test.xml.
Why values are different from Test.xml? Is this a correct approach? Let me know if question is not clear.
I think that you have an issue with inssuficient permissions and windows file virtualization. When your installer creates a file inside Program Files folder, it usually sets permission only for read operations.
When you try to modify the file using an application running at user account that has now write permissions, windows makes an illusion that the file has been successfully written, but puts it in a virtual store - check if such directory/file exists in c:\users\CurrentUserName\Local\VirtualStore\Program Files (x86)\YourFolderName
Only your application can see modified file version, but all other application see original version written by installer.
To be able to modify the file using an application, you need to add write permissions to the file.

How can I update System.Data.SQLite.DLL from an application that uses it?

I have a .NET application that is just an updater for another application. However, Updater uses SQLite to query a database for proxy settings to download the updates from the server. I need to update the SQLite DLL, but of course I get "The process cannot access the file 'C:\Program Files\XXXX\System.Data.SQLite.dll' because it is being used by another process.".
I see on Wikipedia " SQLite is not a separate process that is accessed from the client application, but an integral part of it." But that doesn't seem to be the case.
Can anyone think of a workaround?
If you need to update a library that your application uses, you should use late binding to load the library so you can de-allocate it on demand and then overwrite the file. You are probably early binding it now which will preclude any overwrite while your process is running.
Assuming you have a "main" app that runs the updater app - grab the proxy settings from the main app, then pass them to the updater app on its command-line.
Another option - if your updater app lived in C:\Program Files\XXXX\Updater\, you could update the copy of the SQLite DLL in the main folder without running into conflicts. This isn't ideal, though - you end up with 2 copies of the DLL, and your main app would probably want to update the SQLite DLL in the Updater folder.
And another option - move the proxy configuration settings to something other than a SQLite database. A XML settings file would work pretty well for something like that, and libraries to serialize/deserialize it are built-in to .NET.

System.Addin & ClickOnce

I have a annoying build process from using System.Addins API with ClickOnce. Using System.Addins requires a specific directory structure, and the main project does not reference the adapters, view, and contract directly, which doesn't work well with the ClickOnce architechture.
The annoying part with the build process is that I have to copy, via post build event, the .dlls from the add-in components into the directory of the main app project, then reference those files manually from the main project, so that ClickOnce will include them. Firstly, this takes 2 iterations of build to get it to build correctly, secondly, it interferes with source control (I have to exclude the copied add-in dll files from source control or any changes made to them would require checkout).
So, my question is, is there a way around this hack? Something more elegant?
I can't fully answer your question, but it appears you are creating ClickOnce deployments through Visual Studio. I would ditch that method and use MageUI instead. It's a stand-alone executable that can be found in the framework SDK that will generate your application and deployment manifest files. It comes with a gui version (mageui.exe) and a command line version (mage.exe).
Mage may not get rid of your post-build event but it should do away with having to reference the files to get ClickOnce to see them.
Thanks for your input, I am currently doing it the way you mentioned; creating the folder in my project, and include the dlls that I need. It works, but it's an ugly solution, and it interferes with Source Control.
I'm aware of the limitations of ClickOnce, I was hoping there may be a way around it. For example, I read somewhere that I can use deployment projects to create the appropriate dependencies needed in a specific structure. The problem with that is once it is deployed to the public, there is no easy way (within ClickOnce) to update those dependencies.
The solution I use is to have a single output folder for all projects. Every project puts it's own files in the correct subfolder. The application bootstrapper project puts his dlls also in the output (root) folder. When you then create a click-ones for the bootstrapper, it will take all the content from the output folder.
The hardest part is to actually get all the dll's in the right place (and have every dll only once)
I solved this problem by adding the pipeline assemblies as content into the main solution structure.
To do this, change the output folder from (/bin/debug /bin/Release) to something else. I used ../lib otherwise you would get a visual studio cannot reference this file error.
Create the pipeline folders in your main solution
\AddInSideAdapters
\AddInViews
\Contracts
\HostSideAdapters
Right click on each of the folders and click "add existing item" change to view all files and then browse to your ../lib (or wherever you have the output set) and then pull down the add button (click the down arrow) and click "Add as a Link".
Right click on each file and set it to Content.
This will create a refresh file pointed to your assemblies and they will be included into the clickonce manifest.
ClickOnce do not let you install the software where you want. It will install the binary and dlls in the documents and settings. You can in your project properties go in the Publish tab and select Application Files to select additional file to Include. If the System.Addings require dll in a specific folder relatively to your assembly, you might just create the folder in you project and includes from here the dlls. This might works. If not, I do not have "hack" or other solution, clickonce is great but limited with some functionalities.

Categories

Resources