Selective FTP download using .NET - c#

I have an ftp build site where new builds will be updated.
It will create a new folder named "Build XXXXX" in a specific ftp location for every new build. I need to download the build from a location inside "Build XXXXX"directory (eg. Builds\Build XXXXX\German\iso\German.iso). Here I can't predict number XXXXX.
I'm planning of writing a .NET application to automatically monitor the ftp location for any new Build XXXXX folder and if it is present, the application should download the file at the specified location (ie \German\iso).
How can I do that. Is there any API available for selectively downloading files.
Also, is there any tools already available to do this?

You can simply use the methods of the WebClient class for this.

I don't think there will be any tool tailor made for your requirement. But if you have the client library, you can make one yourself.

Related

How to include externel user files into UWP side-loading package?

Say I use some .json files to descript some object data which effect to the program's behavior, I hope to use these files in the following scenarios
The default values, for this purpose, I need a set of files follows with the application to be packed and installed.
I wish it could be edited by human manually. (Because something have no interface to be modify on UI)
Both user and the program need to kwnow the location the files will be placed after installation.
In debugging stage, I could put these files in the user\AppData\Local.. folder and I know how to access them, but I don't know how to put files into the package and will them generated to anywhere after install?
Thank you for any suggestion.
ps.
I use the "Blank App (WinUI 3 in UWP)" template to create my
application.
I'm new in UWP and WinUI, I used to write traditional Windows Form programs.
How to include externel user files into UWP side-loading package?
You could place the json file into app's project and set the file property as Content, then it will deploy into installtion folder after package install. and please note the json file is readonly in the installtion folder.
so you could call CopyAsync method copy the file to the destination folder that app's local folder with full permission.
For more details about file access permissions please refer this document.

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).

WiX Installer - how to read sql file content from a folder which reside at same location as .msi

I want to invoke custom action to execute set of .sql files against given database. I am able to do that using custom action code(in c#) if I hardcode path of folder where my sql files are available.
I want to put this sql scripts folder in same location where my .msi is present. How can I access/find this folder-path from custom action during the time of installation?
I am using Wix 3.6.
I am using dot net bootstrapper to create my setup.exe.
The SqlScript element in the WiX toolset may do a lot of what you are asking for. It actually stores the scripts as Binary streams in the MSI instead of relying on files relative to the MSI. This is an important design decision because there are many cases where your MSI will execute but not have access to the original source media so it would not find the scripts. For example, repair operations can be launched from the cached MSI package. If your custom action was to repair, it would need the original media to get the scripts. This is not very desirable.
If you really want to go down this path, then you'll want to look at using the SourceDir directory to get the "source location" of your MSI. As noted above, the source media may not always be available and SourceDir will be blank in those cases. To force SourceDir to be set, you'll need to add a ResolveFiles action. Be careful when scheduling ResolveFiles because that will require the original media. If that can't be found, the user will be prompted to insert it again.
The worst case of poor sequencing of ResolveFiles is a prompt from source when the user is attempting to uninstall their product. User's are trying to get your application of the machine and they are prevented unless they can find how they originally installed it. Good way to really upset your users. :)
I highly recommend looking at the SqlScript element instead or the source code if you are really interested. It's in the WiX toolset at src\ca\serverca (look for files with "sql" in the name below there).

Problems Unzipping and Re-zipping an XAP file during installation to Modify a Config File

I have an interesting dilemma to which, I hope, someone may have an answer. My company has a very complex web application which we deliver to our clients via an InstallShield multi-instance installer package. The application is written in ASP.NET MVC3 (using the Web Forms View Engine), C# 4.0, and Silverlight. It is the Silverlight component of the app with which we are having problems during installation.
Many of our clients wish to install our web app in what we refer to as “mixed-binding mode”. This may not be the correct terminology. What I mean to say is that the client will install the web app on a web server that is internal to the client’s firewalls and expose it to the web via a proxy server in the DMZ. In this way, everything internal to the firewall will resolve as HTTP, while every external request will resolve as HTTPS.
This does not pose a problem to most of the web application during installation because it will be running inside the firewall and will ALWAYS be HTTP when the app is installed in “mixed-binding mode”. This is not the case with the Silverlight component. Because it runs in the end-user’s browser process space, it is external to the proxy and firewall and must resolve via HTTPS.
The Silverlight files are in the XAP file. Within the XAP file, we have a configuration file (in XML format) that must be modified based on the binding mode of the web application (HTTP, HTTPS, or MIXED). As we all know, XAP files are simply Zip files, so theoretically all that is needed to edit a file contained in the XAP is to rename it from “.xap” to “.zip” and use any zip compatible utility or library component to extract the configuration file, edit it by some manual or automatic means, and then use the same zip component to re-archive the modified file back into the XAP file.
“Therein lies the rub!” This must take place automatically within the InstallShield Basic MSI process. At first we tried using an InstallShield Managed Code Custom Action using the DotNetZip library; however, DotNetZip seems to have an incompatibility with InstallShield. Every time InstallShield launches the Custom action, the installer would throw a InstallShield 1603 error the moment the custom action tried to execute the first DotNetZip command. (Yes we did rename the XAP file from “.xap” to “.zip” prior to trying to unzip the file.) We encountered the same problem with SharpZipLib.
Next, we dropped down to a lower level algorithm using the Shell32 library. We knew there would be timing considerations to take into account using this method since Shell32 processes run in a separate thread so we built wait states into the process, as shown below:
//Extract the config file from the .zip archive
Shell32.Shell shell = new Shell32.Shell();
string extractedFolderPath = tempZipFileName.Substring(0, tempZipFileName.Length - 4) + "\";
if (Directory.Exists(extractedFolderPath))
Directory.Delete(extractedFolderPath, true);
Directory.CreateDirectory(extractedFolderPath);
//Folder name will have the file extension removed.
Shell32.Folder output = shell.NameSpace(extractedFolderPath);
Shell32.Folder input = shell.NameSpace(tempZipFileName);
foreach (FolderItem F in input.Items())
{
string name = F.Name;
//We only extract the config file
if (name.Equals(CFG_FILE))
{
output.MoveHere(F, 4);
System.Threading.Thread.Sleep(LONG_TIMEOUT);
}
}
//You have to sleep some time here,
// because the shell32 runs in a separate thread.
System.Threading.Thread.Sleep(MED_TIMEOUT);
This seemed to work the “majority” of the time.
NOTE: the use of the word “majority” above. The process works inconsistently on a fast server, whereas it works consistently on a slower machine. Don’t ask me why, my math professors always taught me that a second is a second (in this Universe at least).
We have even tried this with a PowerShell script. In this case, we are able to extract the configuration file and rename it in the target folder to which it was extracted; however, everything we have tried to do copy the renamed file back to the ZIP archive has failed. This is very unusual since we added a second call to push the target folder and all its children into the Zip archive and that works just fine (See the code reference below)!
#Extract_XAP.ps1
#===============
$shell=new-object -com shell.application
#Establish Current Location as Current Location
$CurrentLocation=get-location
#Determine the path of the $CurrentLocation
$CurrentPath=$CurrentLocation.path
#Create a namespace using the $CurrentPath
$Location=$shell.namespace($CurrentPath)
#Rename the XAP File to a ZIP file for extraction will work.
Get-ChildItem *.xap|Rename-Item -NewName {
$_.Name -replace "xap","zip"
}
#Create a ChildItem object using the ZIP file.
$ZipFile = get-childitem SunGard.OmniWA.WebAdmin.zip
#Insure the ZIP File is not readonly
(dir $ZipFile).IsReadOnly = $false
#Create a shell namespace for the ZIP Folder within the ZIP File.
$ZipFolder = $shell.namespace($ZipFile.fullname)
\Iterate through the ZIP Items in the ZIP Folder
foreach ($CurFile in $ZipFolder.items())
{
if ($CurFile.name -eq "ServiceReferences.ClientConfig")
{
#Current item's name matches the file we want to extract,
# so copy it from the ZIP Folder to the Current $Location.
$Location.Copyhere($CurFile)
#Wait briefly to insure process stays in sync
Start-sleep -milliseconds 1000
#Change the extention to the extracted file, so we can tell it from the original when we
# insert it back to the ZIP Folder.
Get-ChildItem *.ClientConfig|Rename-Item -NewName {
$_.Name -replace "ClientConfig","ClientConfig_Test"
}
#Create an object containing the extracted file.
$ClientConfigFile = get-childitem ServiceReferences.ClientConfig_Test
#Wait briefly to insure process stays in sync
Start-sleep -milliseconds 2000
#No need to search further
break
}
}
#For some reason this WILL not copy the renamed file back
# into the ZipFolder, even though it should (see below)!
$ZipFolder.CopyHere($ClientConfigFile)
#For some reason copying the entire current directory
# works just fine! Go figure!
$ZipFolder.CopyHere($Location)
#I hoped this would work, but it doesn't????
$ZipFolder.Close
write-output "renaming to the original extension"
#Rename ZIP file back to a XAP file, so Silverlight can use it.
Get-ChildItem *.zip|Rename-Item -NewName {
$_.Name -replace "zip","xap"
}
This shouldn’t be this hard to do. Somebody has to have done something like this before! I mean any complex web installation is going to need an automated install process and is going to have to be eventually installed using proxies and DMZ’s.
Any assistance would be appreciated. Here are the specifications we must follow:
Use InstallShield Basic MSI as the installer.
Any InstallShield Custom Action must be written in C#.
The XAP file must be modified after the file has been copied to the server by the installer.
Management wants me to stay away from BSD and GNU "free-ware" like
Info-Zip, 7Zip, et.al.
Ken Jinks
Senior Web Developer
Sungard Omni Wealth Services
Birmingham AL
Option 2
Address the 1603 error.
A note I found on this page says:
Verify the correct prototype syntax for entry-point function
declarations of InstallScript custom actions, if any have been
included in the setup.
An example of a correct prototype is: export prototype MyFunction(HWND);
Note: HWND must be specifically referenced
in the prototype. All InstallScript functions called via custom
actions must accept a HWND parameter. This parameter is a handle to
the Microsoft Windows Installer (MSI) database.
Option 1 (not an option)
Putting on my pragmatic hat here:
If you only have the two scenarios, e.g. Mixed-binding and "normal", I would suggest simply generating two ZAP files in your project and installing only one, or (my preference) install both and dynamically deciding which ZAP filename to inject into the hosting page at runtime (if you can identify the running mode in your MVC web app).
This keeps the installer simple and does not add much work to have a few shared main files in each of two Silverlight projects connected to the same web project.
You can use a shared TT include file to generate any configs using a mostly shared config template.
O.K. I have finally figured it out using PowerShell. As it turns out, I could not get any of the CopyHere flags parameter settings to work and CopyHere will not overwrite a file in a zip folder object unless it has been told to do so by the Flags Parameter.
The simplest solution was to change all of the CopyHere methods to MoveHere methods. In that way I was never having to try to overwrite a file and I also never had to delete my working file because it got moved back into the Zip Folder.
Thanks for all of your help.
Ken Jinks

determine SVN checked in state of a file in c#

I currently have a requirement where I need to validate that all the files in a folder structure which are in SVN to see if they are up to date. Is there a way to do this using the svn artefacts that are held in the same directory as the file without interacting with SVN?
Apologies, this appears to need some further explanation...
I'm iterating through the projects loaded within a solution and can access the corresponding files on the file system. I need to check
a) if corresponding files on the file system match the latest revision if the file is under source control and
b) if any or the files or projects have not been added to the SVN.
This is essentially a validation check prior to calling a build server to start a build in case a user has forgotten to check in some changes, new files or new projects to a solution. The build server retrieves the code directly from the source control.
Do you ask how to detect what files stored in SVN folder(s) are changed?
You ask to do that without interacting with SVN, but I would recommend avoid this because file or folder structure can be changed by Subversion team in future.
Try to use SharpSVN I use it in one of my projects. It handy, stable, has nice API and actively developed.
Also check comments in your question. Anyway you can check source code of SharpSVN to undestand how to make it by yourself

Categories

Resources