Tuesday, 18 March 2014

Packaging your Shiny App as an Windows desktop app

Introduction

In developing SkyScorer I've sought ways to package it as a standalone Windows app. The advantages of doing this is quite clear:

  • The end-user doesn't need any R knowledge to run the app
  • The app can be distributed as a simple download
In this tutorial I will go through the process that is needed to create a standalone Windows Shiny app.

Portable R & Chrome


Firstly download Portable R and Portable Chrome. These will serve as the backbone of our app. Essentially, we are packing along with our app self-contained copies of R and Chrome:
  • Portable R: http://sourceforge.net/projects/rportable/
  • Portable Chrome: http://portableapps.com/apps/internet/google_chrome_portable
Once you have downloaded the installation files for Portable R and Portable Chrome just install them and note down their installation path. We will use this later.

For simplicity I will assume you can make a folder in your C Drive called YourApp, but the folder could be situated anywhere. Now copy the portable R installation and the Portable Chrome installation into the C:\YourApp folder. Also copy your Shiny folder containing server.R and ui.R (or a sole app.R in the case of single file Shiny app) into the folder. So now you should have three folders in your C:\YourApp directory
  • C:\YourApp\GoogleChromePortable
  • C:\YourApp\R-Portable
  • C:\YourApp\Shiny

Setting Up Portable R

Just run R-Portable.exe and install all the libraries that are needed by your Shiny app. They will be stored in the Portable R folder. 

Setting Up Portable Chrome

Make sure you have the following line in the GoogleChromePortable.ini file which is in the GoogleChromePortable folder

AdditionalParameters= --app="http://localhost:8888"

The additional parameter there makes Chrome start up in app model (i.e. with address bar, bookmarks etc) which makes it look more like a native app.

The .bat and .vbs files

In the C:\YourApp folder create two files
  • run.vbs
  • runShinyApp.R

The contents
Now WAIT! Don't click on run.vbs just yet! I advise you to add the following to the server.R inside the shinyServer(function(input, output, session)  { ... }). Please make sure you pass session as the third argument! The code you need to add is 

This will close the Rsession when you close the browser (in this case Portable Chrome). Now clicking on run.vbs should start your app!

Simply zip up your folder C:\YourApp and distribute! Your users need only double click on run.vbs to run the app.

If you want to appear more professional you can follow the instruction in the next section to create a setup.exe file for you app.

InnoSetup


Download InnoSetup http://www.jrsoftware.org/isdl.php and install the software and run the Wizard for creating a new setup file. Everything should be pretty self-explanatory, just make sure that InnoSetup knows to use the C:\YourApp directory. Basically InnoSetup will package everything in the directory into an .exe file which acts as a setup wizard.

I chose my default install path to be somewhere other than C:\Program Files as I have found a few issues with it on Windows 8 (no problem on Windows XP).

Once you are done with the InnoSetup Wizard you should end up with a .iss file looking like this 



The code in the .iss file should be self-explanatory. I only added a few lines which I thought was helpful. Under [setup] add PrivilegesRequired=none, this will not request for admin privilege when installing the app so should allow the app to be installed by most users. Also I created a shortcut to the desktop using the below

[Icons]
Name: "{commondesktop}\YourApp"; Filename: "{app}\Apps\run.vbs"; IconFilename: {app}\Your.ico

Of course I have my own custom .ico file to make the shortcut look unique and professional.

Hope this helps!



53 comments:

  1. Kudos for writing out the whole process; very helpful! Will try to get this set up for my own app too.

    ReplyDelete
  2. while running the run.vbs file . it generates .rout file but not starts the browser.

    ReplyDelete
    Replies
    1. Thanks for the bug report. I found some errors with the original post (corrected already).

      So you need these changes (I recommend restarting your computer too):

      change your run.vbs to

      Randomize
      CreateObject("Wscript.Shell").Run "R-Portable\App\R-Portable\bin\R.exe CMD BATCH --vanilla --slave runShinyApp.R" & " " & RND & " ", 0, False

      and your runShinyApp.R to

      .libPaths("./R-Portable/App/R-Portable/library")
      # you need the full path to portable chrome
      browser.path <- file.path(getwd(),"GoogleChromePortable/GoogleChromePortable.exe")
      options(browser = browser.path)
      shiny::runApp("./Shiny/",port=8888,launch.browser=TRUE)

      Delete
  3. Hi,

    I am getting the following error when I was running
    Error in setwd(appDir) : cannot change working directory.

    Please Help !!

    ReplyDelete
    Replies
    1. This error typically occurs if your working directory does not contain the shiny ui.R and server.R files.

      I guess you put print(getwd()) into the runShinyApp.R file and check the .Rout file to see where the working directory is set and update your code according. You can set the working directory using setwd(...)

      Delete
  4. Hi,
    Thank you for the process description.
    Should this be accessible from the other machines within the same LAN? or is it linux required for that?

    ReplyDelete
  5. Wont the App file package become too large; 200MB+ even for a small app as installing chrome and R alone takes that much size. Any workaround to that?

    ReplyDelete
    Replies
    1. I think this approach is meant for substantial apps only. The future is distrbuting apps online anyway.

      Delete
  6. Very nice post! The most recent version of shiny allows one .R file (app.R) instead of two separate files for the ui and server. How would having one app.R file change the approach you outline above? Any chance you might be able to update the tutorial for these cases?

    Great work!

    ReplyDelete
    Replies
    1. Almost nothing has changed. Simply copy the Shiny folder which now should contain app.R instead of server.R and ui.R in the appropriate folder in the tutorial. I have updated the tutorial with a brief sentence

      Delete
    2. Thanks, will give it a shot! Do you have a sense how to do this on a mac?

      Delete
    3. @Isaac

      Check this
      http://www.r-bloggers.com/shell-script-to-build-os-x-shiny-apps-from-github-gists/

      Delete
  7. This is great...if I could get it to work :( I am getting the following warning: http://127.0.0.1:8888' had status 127 in a txt file after hitting the run.vbs. I am sure its my error but any way you could point me to a resource to fix it? thanks!!!

    ReplyDelete
    Replies
    1. No such error for me. Perhaps if you could post your run.vbs and runshiny.r and on gist.github.com? I am happy to have a look

      Delete
    2. Thank you so much!! runShinyApp is here: https://gist.github.com/anonymous/f31176dcc385c177bb1b

      Delete
    3. The run.vbs is here: https://gist.github.com/anonymous/3057cf6266b4c0081497

      I do appreciate your help greatly and can't wait to get this working.

      Delete
    4. See my comments in https://gist.github.com/anonymous/f31176dcc385c177bb1b

      Delete
    5. THANK YOU! Totally works now. Next step for me is the .exe step. Cannot thank you enough.

      Delete
  8. Hello again! Having a bit of trouble getting the innosetup to work...and your .iss file image isn't working. Any chance you have that image handy so I can poach?! thanks.

    ReplyDelete
  9. It help me a lot! Thank you very much!

    ReplyDelete
  10. Works near perfection for me; just have a slight problem this line :
    AdditionalParameters= --app="http://localhost:8888"
    Doesn't work at all : i've tried to change the port and put 127.0.0.1:[port] but nothing happen ..
    Do you have any clue ?

    ReplyDelete
    Replies
    1. Hey Vladimir,

      Had this same problem. Move the googlechromeportable.ini file to the same folder as googlechromeportable.exe

      Problem solved!

      Delete
  11. I managed to use InnoSetup to get the program running on the computer on which I built the setup file. Now I just tried to do the setup on a different computer, and there I get error messages appearing in the app folder (names of these error messages are like decimal numbers 0,.....). In such an error file, there is:

    Loading required package: shiny

    Listening on http://127.0.0.1:8888
    Error in startServer(host, port, handlerManager$createHttpuvApp()) :
    Failed to create server
    Calls: -> startApp -> startServer
    Execution halted

    What is wrong? Does one have to change the runShinyApp.R on that computer? Seems strange...

    ReplyDelete
    Replies
    1. Same problem...Were you able to resolve?

      Delete
    2. I also encountered same problem/error. A slightly modified version is available here which works fine for me http://www.r-bloggers.com/deploying-desktop-apps-with-r/

      Delete
  12. When I click on run.vbs ..it create a file with extn 0.7222101 ..dont know y..Can u please help me on this

    ReplyDelete
  13. Will the app be contacting the shiny server over the internet?
    If yes, will data be sent over the network?

    ReplyDelete
  14. When I try to run the run.vbs file I get the following error
    "Windows Script Host"
    Script:
    Line: 2
    Char: 1
    Error: 0x800700D8
    Code: 800700D8
    Source: (null)
    This works fine on my desktop (windows 7 - 64 bit) but not on my laptop (windows 7 - 32 bit). Anyone knows why that is and how I can fix it?

    ReplyDelete
    Replies
    1. OK, think I figured it out.

      Windows 32 bit users need to change the contents of run.vbs to:

      ####

      Randomize
      CreateObject("Wscript.Shell").Run "R-Portable\App\R-Portable\bin\i386\R.exe CMD BATCH --vanilla --slave runShinyApp.R" & " " & RND & " ", 0, False

      ###

      i.e. change the directory of the 'R.exe' file. If you try to open the original on a 32 bit machine, you'll see it won't open.

      Delete
  15. I followed your instructions and have used server.r and ui.r from "welcome to shiny" tutorial so they are most basic as can be. Still I cant get it running. I am getting a file as output:
    0,8030359

    Do you have any idea what it can be? I would be very grateful for your help. TIA

    Anna

    ReplyDelete
    Replies
    1. OK, think I figured it out.

      Windows 32 bit users need to change the contents of run.vbs to:

      ####

      Randomize
      CreateObject("Wscript.Shell").Run "R-Portable\App\R-Portable\bin\i386\R.exe CMD BATCH --vanilla --slave runShinyApp.R" & " " & RND & " ", 0, False

      ###

      i.e. change the directory of the 'R.exe' file. If you try to open the original on a 32 bit machine, you'll see it won't open.

      Delete
  16. I'm having exactly the same problem as 'Unknown':
    "Windows Script Host"
    Script:
    Line: 2
    Char: 1
    Error: 0x800700D8
    Code: 800700D8
    Source: (null)

    I'm also windows 7 32 bit

    ReplyDelete
    Replies
    1. OK, think I figured it out.

      Windows 32 bit users need to change the contents of run.vbs to:

      ####

      Randomize
      CreateObject("Wscript.Shell").Run "R-Portable\App\R-Portable\bin\i386\R.exe CMD BATCH --vanilla --slave runShinyApp.R" & " " & RND & " ", 0, False

      ###

      i.e. change the directory of the 'R.exe' file. If you try to open the original on a 32 bit machine, you'll see it won't open.

      Delete
  17. I managed to run the run.vbs script which opens the portable chrome browser. But as soon as the browser opens, there seems to be a gray overlay on my page. I assume it means that Shiny has disconnected. Please help. Thanks.

    ReplyDelete
    Replies
    1. Even i'm facing the same problem. Did you find any solution for it?

      Delete
  18. I get the same issue as pokeme. I went to the Chrome developer panel and found this:

    WebSocket is already in CLOSING or CLOSED state.

    Thanks in advance for any guidance you might provide. And thanks for creating this approach and providing it to others.

    ReplyDelete
  19. Excellent work. I made a few modifications and it works perfectly. I am trying to deploy more apps separately from same folder. I tried to make a second runShinyApp.R and .vbs file for another Shiny app and modified them to run this second app. Unfortunately, I couldn't make both apps run at the same time in Chrome. Any thoughts of how this could be done?

    ReplyDelete
  20. Hi,
    I have followed the instructions and set up the portable app. The first line of server.R loads the database. Which is

    lhg <- readRDS("C:/myclient/Shiny/lhg.RDS")

    The browser opens, but getting an error indicating, object 'lhg' not found. Can you please help?

    ReplyDelete
  21. This comment has been removed by the author.

    ReplyDelete
  22. Awesome stuff. thanks a lot for the tutorial.
    one file with log gets created each end every time we run the app. Is there a way to prevent it?

    ReplyDelete
  23. Hi, thanks for the guide it helped me a lot and obviously it works like a charm! But I've got a little issue, the run.vbs file runs my app and generates a file (ex: 0.89334.file) with few lines of comments in it.
    This “.file” isn’t a real issue (it’s only an aesthetic issue, they are not erased when I shut off the app) but I noticed that Chrome Portable keeps on running (in background) even if the app isn’t in use anymore. So if I use and close my app 10 times I’ll have 10 Chrome Portable open processes. Could you help me? Thanks in advance!

    ReplyDelete
  24. Hi, thanks for the guide, when I run run.vbs i get an error message
    "Error in loadNamespace(name) : there is no package called 'shiny'
    Calls: :: ... tryCatch -> tryCatchList -> tryCatchOne ->
    Execution halted"
    can you help me?

    ReplyDelete
  25. Hi, thanks for the guide! when i run run.vbs it gives me a file containing the error message
    "Error in loadNamespace(name) : there is no package called 'shiny'
    Calls: :: ... tryCatch -> tryCatchList -> tryCatchOne ->
    Execution halted"

    ReplyDelete
    Replies
    1. Just Open (double click) GoogleChromePortable.exe [GoogleChromePortable\GoogleChromePortable.exe] and type http://127.0.0.1:8888 your app comes up

      Delete
    2. this same problem comes for me and i am not able to resolve it using the above stated solution
      please help

      Delete
    3. Make sure to open your RPortable and install any packages (including 'shiny') that your app depends on.

      Delete
  26. Thank you very much for your post. It helped me in building a portable version. When I launch the app, it creates a log file Everytime I launch. The issue is I cannot delete it because the process is still alive in task manager.

    Is there a way to avoid this?

    ReplyDelete
  27. I am not able to make it .I followed all the procedures as given.When I run the run.vbs file its giving the error like windows script host error.please can u share ur mail id .I need your help.Or u can ping me to deepikasr03@gmail.com Please help me

    ReplyDelete
  28. I am getting the following error when I try to run the Inno Setup Compiler....

    "could not copy "C:\Program Files (x86)\Inno Setup5\SETUPLDR.E32" to "C:\TestR\setup.exe" Error2: The system cannot find the file specified"

    Please help

    ReplyDelete
  29. thumbs up for the great tutorial still in 2021. Even works with RMarkdown files (but you ll need to copy additional MikTex and Pandoc folders)

    ReplyDelete