Embarcadero C++ : How to notify user if new update is available? - updates

I am beginner in Embarcadero C++, If my application is developed in Embarcadero C++ and installed in client machine then how my application notify user if new update is available? If user clicked on yes button then it will first download the application then install it.
Please let me know if anybody have any Idea.

Here is how I check if new version of program is available on the server, using
Indy Client component TIdHTTP.
Let's say you have uploaded a new version of your application. Besides installation or zip file containing you application, upload a one line text file (applicationBuildData.txt) which contains build value (integer), delimiter (;) and optionally some other data (version number, program name, etc...). For example:
20170215; ProgamName rel. 1.2.
This is the only line in applicationBuildData.txt file. Here is the code sample (I've modified my original code a bit):
void __fastcall TfrmDialog::Button1Click(TObject *Sender)
{
TIdHTTP *IdHTTP1 = new TIdHTTP(this);
// let's say this is current app build (on user's side)
int currAppBuild = 20170101;
int prodBuildNew = 0;
UnicodeString prodVersionNew;
UnicodeString version_str;
try {
// get content of applicationBuildData.txt into string
version_str = IdHTTP1->Get("http://www.your-site.com/applicationBuildData.txt");
prodBuildNew = StrToInt(version_str.SubString(1, version_str.Pos(";") - 1).Trim());
prodVersionNew = version_str.SubString(version_str.Pos(";") + 1, 100).Trim();
}
catch (...)
{
prodBuildNew = 0;
prodVersionNew = "???";
}
if (prodBuildNew == 0) {
// ...faild to get data from server...
// display message
}
else if (prodBuildNew > currAppBuild) {
// new version is available
// display message
}
else {
// application version is up to date
// display message
}
delete IdHTTP1;
}
In this example, current build number is smaller then uploaded build number and it will indicate user that new version is available.
Note: currAppBuild is usually some global constant, or global variable that presents build version. After new version on the server is detected, you can either download installation/zip or simply display message and let the user go to your site and download new version manually.
Edit: How to download the file to your local disk using TIdHTTP component, check the following video:
https://www.youtube.com/watch?v=fcN8K3R4iZE

Related

Enforce Microsoft.Build to reload the project

I'm trying to iteratively (part of automation):
Create backup of the projects in solution (physical files on the filesystem)
Using Microsoft.Build programmatically load and change projects inside of the solution (refernces, includes, some other properties)
Build it with console call of msbuild
Restore projects (physically overriding patched versions from backups)
This approach works well for first iteration, but for second it appears that it does not load restored projects and trying to work with values that I patched on the first iteration. It looks like projects are cached: inside of the csproj files I see correct values, but on the code I see previously patched values.
My best guess is that Microsoft.Build is caching solution/projects in the context of the current process.
Here is code that is responsible to load project and call method to update project information:
private static void ForEachProject(string slnPath, Func<ProjectRootElement> patchProject)
{
SolutionFile slnFile = SolutionFile.Parse(slnPath);
var filtredProjects = slnFile
.ProjectsInOrder
.Where(prj => prj.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat);
foreach (ProjectInSolution projectInfo in filtredProjects)
{
try
{
ProjectRootElement project = ProjectRootElement.Open(projectInfo.AbsolutePath);
patchProject(project);
project.Save();
}
catch (InvalidProjectFileException ex)
{
Console.WriteLine("Failed to patch project '{0}' with error: {1}", projectInfo.AbsolutePath, ex);
}
}
}
There is Reload method for the ProjectRootElement that migh be called before iteraction with content of the project.
It will enforce Microsoft.Build to read latest information from the file.
Code that is working for me:
private static void ForEachProject(string slnPath, Func<ProjectRootElement> patchProject)
{
SolutionFile slnFile = SolutionFile.Parse(slnPath);
var filtredProjects = slnFile
.ProjectsInOrder
.Where(prj => prj.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat);
foreach (ProjectInSolution projectInfo in filtredProjects)
{
try
{
ProjectRootElement project = ProjectRootElement.Open(projectInfo.AbsolutePath);
project.Reload(false); // Ignore cached state, read actual from the file
patchProject(project);
project.Save();
}
catch (InvalidProjectFileException ex)
{
Console.WriteLine("Failed to patch project '{0}' with error: {1}", projectInfo.AbsolutePath, ex);
}
}
}
Note: It better to use custom properties inside of the project and provide it for each msbuild call instead of physical project patching. Please consider it as better solution and use it if possible.

Send data changing page Windows Phone

I'm trying to change page and send some data to the new page just create. Basicaly, I have a page where the user could log, I'm gonna save the informations and then I'm going to open a new page by sendind the information to my "profil" page, where the user will have the information about his account. I'm using the MVVM patern, I don't know if it's going to change something but I ad this precision ;).
Edit: The only solution i have found is to pass the string of my object (gladly it is just strings). Because we can pass strings to another page. But I would prefer to give my object directly, or change my architecture if needed. Like don't create a page but replace my Usercontroles by others :(.
Thanks for the help.
For temp data:
If it is WP silverlight app, we can directly assign object to public property of destination page in OnNavigateFrom event of source page. For example, we can declare a public property A on Dest page, and implement the following in Source page to pass the user object:
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
Dest destPage = e.Content as Dest;
if(destPage != null)
{
User a = new User();
a.UserName = "aa";
a.ID = 1;
destPage.A = a;
}
}
For WP runtime app on WP 8.1, you can directly use Frame.Navigate(TypeName, Object) to pass the parameter.
For persist data:
I will suggest storing the data to local storage on source page and read it from destination page.
If I understand right you should use parameters in navigate URI
For example to send name you can use:
NavigationService.Navigate(new Uri("/View/Page.xaml?name=UserName", UriKind.Relative));
and then in OnNavigatedTo() check name parameter:
string name;
NavigationContext.QueryString.TryGetValue("name", out name);
You can use IsolatedStorageSettings.ApplicationSettings["keyname"]=yourobject;
And whenever you want to use this value just unbox this value as below,
if(IsolatedStorageSettings.ApplicationSettings.Contains("keyname"))
{
var obj=(yourobject)IsolatedStorageSettings.ApplicationSettings["keyname"];
}

Windows Phone 8 choose text file C#

i have a question. If there is a possibility at windows phone 8 at visual studio to create button event to read text file? i know about streamReader and if i declare wchich exacly file i want to read, but if i want to choose from list of files wchich i want to display. i did research on the Internet but i didint find an answer. I know i can use isolatedStorage to read music, video, image but not text files, on the app i created few files with text in it and i want users to have posibility to display one from this file, whichever they want to see. So, can you tell me how to do this?
You can use IsolatedStorage to read any file type you wish. You must of been using something like a Launcher that filters out the file type based on the Chooser.
You can open a file like this:
private async Task<string> ReadTextFile(string file_name)
{
// return buffer
string file_content = "";
// Get the local folder
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
if (local != null)
{
// Get the file
StorageFile file;
try
{
file = await local.GetFileAsync(file_name);
}
catch (Exception ex)
{
// no file, return empty
return file_content;
}
// Get the stream
System.IO.Stream file_stream = await file.OpenStreamForReadAsync();
// Read the data
using (StreamReader streamReader = new StreamReader(file_stream))
{
file_content = streamReader.ReadToEnd(); // read the full text file
streamReader.Close();
}
// Close the stream
file_stream.Close();
}
// return
return file_content;
}
If you want to get the PackageLocation (files that you added into the project like assets and images) then replace the LocalFolder with
Windows.ApplicationModel.Package package = Windows.ApplicationModel.Package.Current;
Windows.Storage.StorageFolder installedLocation = package.InstalledLocation;
With Windows Phone 8.1, File Pickers are allowed, consisting the same functionality you are expecting, so probably you might want to upgrade your app to WP8.1.
Here's more info on this API : Working with File Pickers

Debugging WP8 Native Code using a file

I'm developing a WP8 app that has some native code (runtime component).
Inside the runtime component I need to check to content of a c style array.
Because this array is not small, I thought the best I could do is write the array in a file
using fopen/fwrite/fclose;
Checking the returned value from fopen and fwrite, I can see that it succeeded.
But I cannot find the file (using Windows Phone Power Tools).
So where has the file been written?
Is there another way to dump the content of the array to a file (on the computer) from visual studio ?
I'm unfamiliar with the fopen/fwrite/fclose APIs in WP8. Which probably means it's not a whitelisted API you can use to submit your app with. It's best if you just use "Windows::Storage::ApplicationData::Current->LocalFolder" when working with IsoStore in C++. See Win8 code sample # http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh700361.aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-1
Thanks Justin,
here's how I ended up doing it:
auto folder = Windows::Storage::ApplicationData::Current->LocalFolder;
Concurrency::task<Windows::Storage::StorageFile^> createFileOp(
folder->CreateFileAsync(L"Data.bin", Windows::Storage::CreationCollisionOption::ReplaceExisting));
createFileOp.then(
[nData, pData](Windows::Storage::StorageFile^ file)
{
return file->OpenAsync(Windows::Storage::FileAccessMode::ReadWrite);
})
.then([nData, pData](Windows::Storage::Streams::IRandomAccessStream^ stream)
{
auto buffer = ref new Platform::Array<BYTE>(pData, nData);
auto outputStream = stream->GetOutputStreamAt(0);
auto dataWriter = ref new Windows::Storage::Streams::DataWriter(outputStream);
dataWriter->WriteBytes(buffer);
return dataWriter->StoreAsync();
})
.wait();
Now compare that to what I "meant" :
FILE *fp = fopen("Data.bin", "wb");
if (fp)
{
int ret = fwrite(pData, 1, nData, fp);
fclose(fp);
}

Is there a way generate a shortcut file with adobe air?

Good afternoon,
I would like create a application that can can create folders and short cuts to folders in the file system. The user will click a button and it will put a folder on there desktop that has short cuts to files like //server/folder1/folder2 Can you create a desktop shortcut with code in adobe air? How would you do that? How do you create a folder? I keep thinking this should be easy but i keep missing it.
Thank you for your help sorry for the trouble,
Justin
If your deployment profile is Extended Desktop, you may be able to use NativeProcess and some simple scripts that you could package with your app. This approach would entail handling the functionality on a per OS basis, which would take some work and extensive testing. However, I wanted to at least share a scenario that I verified does work. Below is a test case that I threw together:
Test Case: Windows 7
Even though the Adobe documentation says that it prevents execution of .bat files, apparently it doesn't prevent one from executing the Windows Scripting Host: wscript.exe. This means you can execute any JScript or VBScript files. And this is what you would use to write a command to create a shortcut in Windows (since Windows doesn't have a commandline command to create shortcuts otherwise).
Here's a simple script to create a shortcut command, which I found on giannistsakiris.com, (converted to JScript):
// File: mkshortcut.js
var WshShell = new ActiveXObject("WScript.Shell");
var oShellLink = WshShell.CreateShortcut(WScript.Arguments.Named("shortcut") + ".lnk");
oShellLink.TargetPath = WScript.Arguments.Named("target");
oShellLink.WindowStyle = 1;
oShellLink.Save();
If you package this in your application in a folder named utils, you could write a function to create a shortcut like so:
public function createShortcut(target:File, shortcut:File):void {
if (NativeProcess.isSupported) { // Note: this is only true under extendedDesktop profile
var shortcutInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
// Location of the Windows Scripting Host executable
shortcutInfo.executable = new File("C:/Windows/System32/wscript.exe");
// Argument 1: script to execute
shortcutInfo.arguments.push( File.applicationDirectory.resolvePath("utils/mkshortcut.js").nativePath);
// Argument 2: target
shortcutInfo.arguments.push("/target:" + target.nativePath);
// Argument 3: shortcut
shortcutInfo.arguments.push("/shortcut:" + shortcut.nativePath);
var mkShortcutProcess = new NativeProcess();
mkShortcutProcess.start(shortcutInfo);
}
}
If one wanted to create a shortcut to the Application Storage Directory on the Desktop, the following would suffice:
var targetLocation:File = File.applicationStorageDirectory;
var shortcutLocation:File = File.desktopDirectory.resolvePath("Shortcut to My AIR App Storage");
createShortcut(targetLocation, shortcutLocation);
Obviously there's a lot of work to be done to handle different OS environments, but this is at least a step.
As far as I know, File class does not allow the creation of symbolic links. But you can create directories with createDirectory(): http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/filesystem/File.html#createDirectory%28%29
Check if this can be useful: http://www.mikechambers.com/blog/2008/01/17/commandproxy-net-air-integration-proof-of-concept/
Air doesnt let you create shortcuts natively. Here's a workaround that works with Windows [may work on Mac but I don't have a machine to test].
Using Air, create a file that contains the following plain text
[InternetShortcut]
URL=C:\path-to-folder-or-file
Replace path-to-folder-or-file with your folder/file name
Save the file as test.url
Windows recognizes this file as a shortcut.
It is possible to coerce Adobe Air into creating symbolic links, other useful things, on a Mac. Here's how I did it:
You will need AIRAliases.js - Revision: 2.5
In the application.xml add:
<!-- Enables NativeProcess -->
<supportedProfiles>extendedDesktop desktop</supportedProfiles>
In the Air app JavaScript:
// A familiar console logger
var console = {
'log' : function(msg){air.Introspector.Console.log(msg)}
};
if (air.NativeProcess.isSupported) {
var cmdFile = air.File.documentsDirectory.resolvePath("/bin/ln");
if (cmdFile.exists) {
var nativeProcessStartupInfo = new air.NativeProcessStartupInfo();
var processArgs = new air.Vector["<String>"]();
nativeProcessStartupInfo.executable = cmdFile;
processArgs.push("-s");
processArgs.push("< source file path >");
processArgs.push("< link file path >");
nativeProcessStartupInfo.arguments = processArgs;
nativeProcess = new air.NativeProcess();
nativeProcess.addEventListener(air.NativeProcessExitEvent.EXIT, onProcessExit);
nativeProcess.addEventListener(air.ProgressEvent.STANDARD_OUTPUT_DATA, onProcessOutput);
nativeProcess.addEventListener(air.ProgressEvent.STANDARD_ERROR_DATA, onProcessError);
nativeProcess.start(nativeProcessStartupInfo);
} else {
console.log("Can't find cmdFile");
}
} else {
console.log("Not Supported");
}
function onProcessExit(event) {
var result = event.exitCode;
console.log("Exit Code: "+result);
};
function onProcessOutput() {
console.log("Output: "+nativeProcess.standardOutput.readUTFBytes(nativeProcess.standardOutput.bytesAvailable));
};
function onProcessError() {
console.log("Error: "+nativeProcess.standardError.readUTFBytes(nativeProcess.standardError.bytesAvailable));
};
Altering the syntax of the command and parameters passed to NativeProcess you should be able to get real shortcuts on Windows too.