Instantly Increase the Value of your Windows Application

Take your desktop application to the web.We already published a very popular article at CodeProject to discuss how the migration of PC desktop users to all kind of mobile devices affected the paradigm of software development.

The bring your own device (BYOD) era started more than a decade ago with Palms and the first smartphones, and now there are much more complex needs to solve. The exponential market growth of Chromebook, iPads and tablets demands a new approach to adapting applications to meet their users’ daily requirements. Continue reading

Use Cookies to Extend a Web-enabled App’s Login

remote data persistence using cookiesIn a previous post we explained how to add remote data persistence to your apps by saving cookies in the browser. In this opportunity we will take advantage of this feature to develop a small but useful demo that shows how to provide an extended sign-on for web users.

Thinfinity VirtualUI web enabled apps were born as desktop apps and most include their own login mechanism. In this opportunity, we will show you how to extend your own existing application’s sign-on process, getting the browser to identify the application’s user. In this way, users would only need to manually log in when accessing the application for the first time, after logging out or when the login ID has expired. Continue reading

All about Thinfinity VirtualUI

Thinfinity VirtualUI Tutorial: What it is? What does it do?

THINFINITY_virtualUI_Guide_smooth

With Thinfinity VirtualUI, any developer can create dual-platform applications (Windows/HTML5) by adding only one line of code to their existing projects built in .Net, Delphi, Visual C++, Virtual Basic or others.

Thinfinity VirtualU allows these applications to be run normally on a Windows environment, or installed in a Thinfinity VirtualUI Server environment and be accessed remotely from any HTML5-compliant Web browser.

Check out these press releases:

 

Would you like to see some online demos?

Find them here.

 

What about jsRO?

Thinfinity VirtualUI relies on Javascript Remote Objects (jsRO), a brand new technology conceived by Cybele Software that enables the creation of remotable server objects, mirrored to the web as native Javascript objects.

jsRO provides full two-way data-binding and remote procedure calls using an easy and straight-forward methodology -making the integration of Windows desktop and web access as easy as pie!

 

Thinfinity VirtualUI is the key

Video 1

You now have the opportunity to take your app to the web in a few minutes.

Thinfinity VirtualUI web-enables Windows Apps with just a single line of code. And it works with popular Windows development environments and programming languages!

When using VirtualUI there’s no need for costly virtualization or remoting environments such as Citrix XenApp® or Microsoft™ RemoteApp, hence slashing IT costs and simplifying maintenance and administration.

Read more about the many Thinfinity VirtualUI benefits.

 

Thinfinity VirtualUI Guide for a Smooth First Time User Experience

Thinfinity VirtualUI is designed to have a straightforward implementation.

Completing the whole Thinfinity VirtualUI installation and setup will only take a couple of minutes before you can enjoy access to your desktop application from a browser in a pure HTML5 interface.

We’ve prepared an article to tell you about some tips and tricks that can help you save time and ensure you have a smooth first time user experience.

 

###

 

Additional documentation:

Product Pagehttp://www.cybelesoft.com/Thinfinity/VirtualUI/
White paper: http://www.cybelesoft.com/docs/thinfinity_virtualui_whitepaper.pdf
Online manualhttp://www.cybelesoft.com/helps/thinfinity/virtualui/

 

Contact:

For more information about Thinfinity VirtualUI, contact Cybele Software, Inc.
3422 Old Capitol Trail, Suite 1125
Wilmington, DE – 19808, USA.
Phone: (302) 892-9625 or (866) 462-9768 (USA & Canada)
Email: info@cybelesoft.com
Website: www.cybelesoft.com

Preview: Thinfinity VirtualUI session recording

Thinfinity VirtualUI session recordingComing soon, Thinfinity VirtualUI web-enabled applications will allow you to save application sessions and replay them later.

There are many scenarios for session recording: reproduction of issues, application demos and tutorials, technical support, audit monitoring, e-learning, etc.

In a previous post we explained how to record and play Thinfinity Remote Desktop Server sessions. In this opportunity, we will review a similar Thinfinity VirtualUI feature that helps developers record sessions of their own VirtualUI web-enabled applications.

Continue reading

Download files from VirtualUI web-enabled apps

Download files with Thinfinity Virtualui

Thinfinity VirtualUI web-enabled applications allow you to programmatically send files to be downloaded in the browser. There are no secrets to that, but the VirtualUI.DownloadFile method has variations enough to deserve a short post in this blog.

There are three ways to call this method:

 

  • Passing the local file name as an argument,
  • Passing the local and remote file names as arguments,
  • Passing both filenames and the MIME file type as arguments.

 

Each argument of the DownloadFile method defines more precisely how the file will be handled in the browser. Continue reading

Passing command line arguments to VirtualUI apps

VirtualUI command-line argumentsAn application can accept command line arguments when invoked. This allows the user to send additional information to the application when it is executed.

When an application is launched, the OS passes the command line arguments to the application as a collection of string values, using a white-space as separator.

Applications receive external arguments on a regular basis: when you open a document by clicking on its icon, the OS selects the associated executable program and calls it, sending the full document filename to the program as an argument.

Thinfinity VirtualUI allows you to send external arguments to applications in a transparent way, which works exactly like sending arguments from the command line.

Continue reading

Using the Analytics Remote Desktop Web Service

In the previous post we discussed the Thinfinity Remote Desktop Web service modules. In this article, we will show you how to set up the ThinRDPWS-Query web service demo for .Net.

 

The ThinRDPWS-Query demo

The ThinRDPWS-Query demo was developed in C# to present the many integration possibilities the Analytics Web Service provides you. This application shows Thinfinity Remote Desktop Server activity information concerning logins, sessions, connections and browsers used to access remote computers in several time intervals.

Continue reading

Browser within the browser: breaking the Matryoshka effect.

When the browsers are nested.
image01

It has become increasingly common to expect desktop applications to be capable of integrating to the web to incorporate available external information. There are several ways this could be achieved: by consuming web services to get the raw data; or, by simply including a browser component within the application, in the form of a panel. In this second case, we’ll be capable of navigating to sites displaying up-to-date information or external multimedia content, such as maps, videos, images and sound —as an example, visit Fish Facts, a live demo that shows basic GUI virtualization capabilities as well as an integration with the web browser and external web resources.

Once we transform these applications with Thinfinity® VirtualUI™, and we invoke them from the web, an effect similar to the famous Russian Nested Dolls case occurs: we run from the browser an application that contains within itself another browser. In short, we surf to an application that internally re-surfs. This is not bad in itself, but we can take advantage of already being in the web to access the final resource directly from the main browser. By doing this we will avoid a roundabout that, among other things, would unnecessarily increase the consumption of resources.

Let’s take a look at the diagrams of the same application running from the desktop…

Matryoshka-image1

… and from the Web:

Matryoshka-image2

As we can see, when we run the application from the desktop we must necessarily navigate through an embedded Webbrowser component. The application is the one that connects to the desired web address, and this webpage is seen in an internal panel, within the application.

But once we load the application from a browser we would experience the aforementioned effect. As a result, the application browses on its own, and the visible result of that surfing is re-transferred to our browser.

If we transfer that navigation to the only browser we need to use, we will access the intended resource without delay or additional bandwidth, processing, or time consumption.

image00

The demo application

The application we use in the example (whose complete source can be found here) attempts to break this browser-within-the-browser effect, simply by using the internal browser only when the application is accessed from the desktop. If the application is being accessed from the web, instead of using that component, the app would load the desired page in an iframe created on the fly. To achieve this integration (which requires a little bit more interaction between the application and the browser) we will add a jsRO object, which will control the remote iframe from the application.

The first addition to our application will be the adding of VirtualUI and its initialization:

using System;
using System.Windows.Forms;

namespace matryoshka
{
   static class Program
   {
       /// <summary>
       /// The main entry point for the application.
       /// </summary>
       [STAThread]
       static void Main()
       {
           new Cybele.Thinfinity.VirtualUI().Start();
           Application.EnableVisualStyles();
           Application.SetCompatibleTextRenderingDefault(false);
           Application.Run(new Form1());
       }
   }
}

Let’s now see what we have to add to the main form code, which it only has a panel where to enter the browsing URL and another one where the WebBrowser component is located.

The following is the application code before adding the changes:

using System;
using System.Drawing;
using System.Windows.Forms;

namespace matryoshka
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            // Sets Google Maps URL to run in the embedded browser
            txtURL.Text = "https://maps.google.com";
            Navigate();
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            Navigate();
        }

        private void txtURL_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (Convert.ToInt32(e.KeyChar) == 13)
            {
                Navigate();
            }
        }

        private void Navigate()
        {
            if (!txtURL.Text.Equals(""))
            {
                if (!txtURL.Text.StartsWith("http"))
                {
                    txtURL.Text = "http://" + txtURL.Text;
                }
                webBrowser1.Navigate(new Uri(txtURL.Text));
            }
            else {
                webBrowser1.Navigate(new Uri("about:_blank"));
            }
        }
    }
}

As a first step, we will add to the class the objects in the Cybele.Thinfinity library:

using System;
using System.Drawing;
using System.Windows.Forms;
using Cybele.Thinfinity;

namespace matryoshka
{
    public partial class Form1 : Form
    {

        private VirtualUI vui = new VirtualUI();
        private IJSObject mRemoteLayout = null;

        public Form1()
        ...

This demo application loads a Google Map. To be run embedded in an iframe, Google Maps needs a different URL from the one used on a full page. We know that it will run embedded in the iframe (using VirtualUI) and directly when loaded into the internal browser.

public Form1()
{
    InitializeComponent();
    if (vui.Active)
    {
        // Code executed only when the application runs with Thinfinity VirtualUI
        // Sets Google Maps URL to run embedded in an iframe
        txtURL.Text = "https://www.google.com/maps/embed";
    }
    else
    {
        //* Code executed only when the application runs from desktop 
        // Sets Google Maps URL to run in the embedded browser
        txtURL.Text = "https://maps.google.com";
    }
}

Additionally, we must also make some changes to Navigate( ):

private void Navigate()
{
    string sURL = "";
    if (txtURL.Text.Equals("")){
        sURL = "about:_blank";
    } 
    else
    {
        sURL = txtURL.Text;
        if (!sURL.StartsWith("http"))
        {
            sURL = "http://" + sURL;
        }
    }
    if (vui.Active) {
        mRemoteLayout.Properties["url"].AsString = sURL;
    }
    else {
        webBrowser1.Navigate(new Uri(sURL));
    }
} 

The last (but not least important) addition is the one concerning the jsRO object management: the first method, for its instantiation and definition of their getters; the other one, for the later updating of the iframe’s bounds.

private void Form1_Shown(object sender, EventArgs e)
{
    // Creates jsRO object for iframe control
    mRemoteLayout = new JSObject("layout");
    mRemoteLayout.Properties.Add("windowId").AsString =
                String.Format("virtualui_canvas_{0}", Handle);
    mRemoteLayout.Properties.Add("url").AsString = txtURL.Text;
    mRemoteLayout.Properties.Add("bounds")
        .OnGet(new JSBinding(        // Adds a "getter" to bounds
            delegate(IJSObject AObj, IJSProperty AProp)
            {
                // Returns a JSON object
                Point p = pnlNav.PointToScreen(new Point(0, 0));
                p.Offset(-Left, -Top);
                AProp.AsJSON = "{" + String.Format("\"left\":{0}, \"top\":{1}, \"width\":{2}, \"height\":{3}",
                     p.X, p.Y, pnlNav.Width, pnlNav.Height) + "}";
            }));
    mRemoteLayout.ApplyModel();
}

private void pnlNav_Resize(object sender, EventArgs e)
{
    // Updates all mRemoteLayout's properties "getters"
    if (mRemoteLayout != null)
    {
        mRemoteLayout.ApplyChanges();
    }
}

We can now introduce the additional information that must be included, at javascript level, to the HTML page.

What follows is the base page to which we will be adding the functionality:

 

We will now create three global variables for the VirtualUI and jsRO objects, and for the iframe created on the fly.

<script type="text/javascript">
var virtualUI = null;
var jsro = null;
var nav = null;

$(document).ready(function () {
    ...

We will add three functions intended to create the iframe and keep it updated:

...
$(document).ready(function () {

    var navigate = function(url) {
        nav.src = url;
    }

    var applyBounds = function(bounds) {
        nav.style.left = bounds.left + "px";
        nav.style.top = bounds.top + "px";
        nav.style.width = bounds.width + "px";
        nav.style.height = bounds.height + "px";
    }

    var createNav = function () {
        nav = document.createElement("iframe");
        nav.id = "nav";
        nav.style.position = "absolute";
        nav.style.display = "none";
        nav.style.zIndex = 2;
        nav.style.border = "none";
    }
    ...

We will now instantiate the VirtualUI object, configure its events, and then connect to the application:

var createNav = function () {
   ...
   ...
}

virtualUI = new Thinfinity.VirtualUI();

virtualUI.onError = function (errorMsg) {
    alert("Application load failed");
};

virtualUI.onLoading = function () {
    console.log((virtualUI.devMode) ? "Waiting for application..." : "Loading...");
};

virtualUI.onClose = function (url) {
    if ((typeof url != 'undefined') && (url != '') && (url != null)) {
        if ((virtualUI.devMode != true) || (window.top.opener)) {
           window.top.close();
        }
        window.top.location.href = url;
        return;
    }
    if (virtualUI.devMode) { location.reload(); }
    if ((virtualUI.devMode != true) || (window.opener)) { window.close(); }
    if ((window.top == window) && (document.referrer) && (location.href != document.referrer)) {
        location.href = document.referrer;
    } 
    else {
        if (nav) { nav.style.display = "none"; }
        alert("Application closed");
    }
};

// -- Connect to server...
virtualUI.connect();

Finally, we will create the jsRO object instance. Please note that it’s in the creation of the layout jsRO model (defined in the application) where the iframe is injected into the application window. The other two events are used to keep both the URL and the inserted iframe bounds updated:

...
virtualUI.connect();

// Defining Javascript Remote Objects Elements
jsro = new Thinfinity.JsRO();

jsro.on('model:layout', 'created', function (obj) {
    layout = jsro.model.layout;
    if (nav == null) {
        createNav();
        document.getElementById(layout.windowId).appendChild(nav);
        nav.style.display = "inline-block";
    }
    applyBounds(layout.bounds);
});

jsro.on('model:layout.url', 'changed', function (obj) {
    navigate(obj.value);
});

jsro.on('model:layout.bounds', 'changed', function (obj) {
    applyBounds(layout.bounds);
});

With this procedure, we’ve been able to break the “Matryoshka Effect”. From now on, the embedded browser will be used from the desktop, while the external one will be used from the web —but always being controlled by the remote application.

 

Running the application from the browser

To see the end result, we must first add the application to the list of registered apps in the Thinfinity VirtualUI Server and configure its home page, making sure it points to the page modified by us in this tutorial.

Once this is done, we can access the application from the browser. If we are running the application from the Thinfinity VirtualUI Development Lab, we must change the virtual path’ address so as to match the one defined in the configuration —in the VirtualUI’s manager.

 

Recovering browser information using ‘BrowserInfo’

Recovering browser information using BrowserInfo propertyWe start with this lines a new series of small articles to offer some simple but useful tips to help provide a better end user experience with Thinfinity® VirtualUI™ extended applications.

When the application was originally designed, the underlying assumption was that it would be used in desktop devices. As a result, we did not spend too much time thinking about the characteristics of the device from where our application would be run.

But when using VirtualUI, it is often necessary to be aware of some features and capabilities of the device from which end users are accessing our application.

The VirtualUI class has a property called BrowserInfo, which contains data about the used browser to assist us in delivering the best possible user experience.

In the list below we will find a detail of the information that BrowserInfo will deliver us:
Continue reading

Windows and Web integration through Thinfinity® jsRO (Javascript Remote Objects) – Part 4

To achieve more interaction between the remote application and the browser, the object model provided by jsRO allows for the creation of remote methods and events defined in the application and added to a model by the developer.

Having learned how to interact with jsRO objects and their properties in previous articles, let’s see now how to create jsRO remote methods and custom events, and how to work with them from both the application and the browser side.

  Continue reading