diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9a69d3bbf..a7d3dbf92 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,6 +3,7 @@ project(PrusaSlicer)
 
 include("version.inc")
 include(GNUInstallDirs)
+include(CMakeDependentOption)
 
 set(SLIC3R_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
 file(TO_NATIVE_PATH "${SLIC3R_RESOURCES_DIR}" SLIC3R_RESOURCES_DIR_WIN)
@@ -32,6 +33,8 @@ option(SLIC3R_MSVC_COMPILE_PARALLEL "Compile on Visual Studio in parallel" 1)
 option(SLIC3R_MSVC_PDB          "Generate PDB files on MSVC in Release mode" 1)
 option(SLIC3R_PERL_XS           "Compile XS Perl module and enable Perl unit and integration tests" 0)
 option(SLIC3R_ASAN              "Enable ASan on Clang and GCC" 0)
+# If SLIC3R_FHS is 1 -> SLIC3R_DESKTOP_INTEGRATION is always 0, othrewise variable.
+CMAKE_DEPENDENT_OPTION(SLIC3R_DESKTOP_INTEGRATION "Allow perfoming desktop integration during runtime" 0 "NOT SLIC3R_FHS" 0)
 
 set(OPENVDB_FIND_MODULE_PATH "" CACHE PATH "Path to OpenVDB installation's find modules.")
 
@@ -71,6 +74,10 @@ if (SLIC3R_GUI)
     add_definitions(-DSLIC3R_GUI)
 endif ()
 
+if(SLIC3R_DESKTOP_INTEGRATION)
+    add_definitions(-DSLIC3R_DESKTOP_INTEGRATION)
+endif ()
+
 if (MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
     set(IS_CLANG_CL TRUE)
 
diff --git a/src/slic3r/GUI/DesktopIntegrationDialog.cpp b/src/slic3r/GUI/DesktopIntegrationDialog.cpp
index a2f7c8933..1ec008bd5 100644
--- a/src/slic3r/GUI/DesktopIntegrationDialog.cpp
+++ b/src/slic3r/GUI/DesktopIntegrationDialog.cpp
@@ -1,15 +1,18 @@
 #ifdef __linux__
 #include "DesktopIntegrationDialog.hpp"
 #include "GUI_App.hpp"
+#include "GUI.hpp"
 #include "format.hpp"
 #include "I18N.hpp"
 #include "NotificationManager.hpp"
 #include "libslic3r/AppConfig.hpp"
 #include "libslic3r/Utils.hpp"
 #include "libslic3r/Platform.hpp"
+#include "libslic3r/Config.hpp"
 
 #include <boost/filesystem.hpp>
 #include <boost/log/trivial.hpp>
+#include <boost/dll/runtime_symbol_info.hpp>
 
 #include <wx/filename.h>
 #include <wx/stattext.h>
@@ -17,9 +20,9 @@
 namespace Slic3r {
 namespace GUI {
 
-namespace integrate_desktop_internal{
+namespace {
 // Disects path strings stored in system variable divided by ':' and adds into vector
-static void resolve_path_from_var(const std::string& var, std::vector<std::string>& paths)
+void resolve_path_from_var(const std::string& var, std::vector<std::string>& paths)
 {
     wxString wxdirs;
     if (! wxGetEnv(boost::nowide::widen(var), &wxdirs) || wxdirs.empty() )
@@ -34,7 +37,7 @@ static void resolve_path_from_var(const std::string& var, std::vector<std::strin
     paths.push_back(dirs);
 }
 // Return true if directory in path p+dir_name exists
-static bool contains_path_dir(const std::string& p, const std::string& dir_name)
+bool contains_path_dir(const std::string& p, const std::string& dir_name)
 {
     if (p.empty() || dir_name.empty()) 
        return false;
@@ -47,7 +50,7 @@ static bool contains_path_dir(const std::string& p, const std::string& dir_name)
     return false;
 }
 // Creates directory in path if not exists yet
-static void create_dir(const boost::filesystem::path& path)
+void create_dir(const boost::filesystem::path& path)
 {
     if (boost::filesystem::exists(path))
         return;
@@ -58,7 +61,7 @@ static void create_dir(const boost::filesystem::path& path)
         BOOST_LOG_TRIVIAL(error)<< "create directory failed: " << ec.message();
 }
 // Starts at basic_path (excluded) and creates all directories in dir_path
-static void create_path(const std::string& basic_path, const std::string& dir_path)
+void create_path(const std::string& basic_path, const std::string& dir_path)
 {
     if (basic_path.empty() || dir_path.empty())
        return;
@@ -76,7 +79,7 @@ static void create_path(const std::string& basic_path, const std::string& dir_pa
     create_dir(path);
 }
 // Calls our internal copy_file function to copy file at icon_path to dest_path
-static bool copy_icon(const std::string& icon_path, const std::string& dest_path)
+bool copy_icon(const std::string& icon_path, const std::string& dest_path)
 {
     BOOST_LOG_TRIVIAL(debug) <<"icon from "<< icon_path;
     BOOST_LOG_TRIVIAL(debug) <<"icon to "<< dest_path;
@@ -90,8 +93,8 @@ static bool copy_icon(const std::string& icon_path, const std::string& dest_path
     return true;
 }
 // Creates new file filled with data.
-static bool create_desktop_file(const std::string& path, const std::string& data)
-{
+bool create_desktop_file(const std::string& path, const std::string& data)
+{    
     BOOST_LOG_TRIVIAL(debug) <<".desktop to "<< path;
     std::ofstream output(path);
     output << data;
@@ -109,10 +112,6 @@ static bool create_desktop_file(const std::string& path, const std::string& data
 // methods that actually do / undo desktop integration. Static to be accesible from anywhere.
 bool DesktopIntegrationDialog::is_integrated()
 {
-	const char *appimage_env = std::getenv("APPIMAGE");
-    if (!appimage_env) 
-        return false;
- 
     const AppConfig *app_config = wxGetApp().app_config;
     std::string path(app_config->get("desktop_integration_app_path"));
     BOOST_LOG_TRIVIAL(debug) << "Desktop integration desktop file path: " << path;
@@ -126,10 +125,6 @@ bool DesktopIntegrationDialog::is_integrated()
 }
 bool DesktopIntegrationDialog::integration_possible()
 {
-
-	const char *appimage_env = std::getenv("APPIMAGE");
-    if (!appimage_env)
-        return false;
     return true;
 }
 void DesktopIntegrationDialog::perform_desktop_integration()
@@ -143,14 +138,26 @@ void DesktopIntegrationDialog::perform_desktop_integration()
         try {
             appimage_path = boost::filesystem::canonical(boost::filesystem::path(appimage_env)).string();
         } catch (std::exception &) {            
+            BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - boost::filesystem::canonical did not return appimage path.";
+            show_error(nullptr, _L("Performing desktop integration failed - boost::filesystem::canonical did not return appimage path."));
+            return;
         }
     } else {
-        // not appimage - not performing
-        BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - not Appimage executable.";
-        wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationFail);
-        return;
+        // not appimage - find executable
+        appimage_path = boost::dll::program_location().string();
+        //appimage_path = wxStandardPaths::Get().GetExecutablePath().string();
+        BOOST_LOG_TRIVIAL(debug) << "non-appimage path to executable: " << appimage_path;
+        if (appimage_path.empty())
+        {
+            BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - no executable found.";
+            show_error(nullptr, _L("Performing desktop integration failed - Could not find executable."));
+            return; 
+        }
     }
 
+    // Escape ' characters in appimage, other special symbols will be esacaped in desktop file by 'appimage_path'
+    //appimage_path = std::regex_replace(appimage_path, std::regex("\'"), "\\\'");
+
     // Find directories icons and applications
     // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. 
     // If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used. 
@@ -158,8 +165,8 @@ void DesktopIntegrationDialog::perform_desktop_integration()
     // The directories in $XDG_DATA_DIRS should be seperated with a colon ':'.
     // If $XDG_DATA_DIRS is either not set or empty, a value equal to /usr/local/share/:/usr/share/ should be used. 
     std::vector<std::string>target_candidates;
-    integrate_desktop_internal::resolve_path_from_var("XDG_DATA_HOME", target_candidates);
-    integrate_desktop_internal::resolve_path_from_var("XDG_DATA_DIRS", target_candidates);
+    resolve_path_from_var("XDG_DATA_HOME", target_candidates);
+    resolve_path_from_var("XDG_DATA_DIRS", target_candidates);
 
     AppConfig *app_config = wxGetApp().app_config;
     // suffix string to create different desktop file for alpha, beta.
@@ -186,7 +193,6 @@ void DesktopIntegrationDialog::perform_desktop_integration()
         icon_theme_dirs = "/hicolor/96x96/apps";
     }
     
-    
     std::string target_dir_icons;
     std::string target_dir_desktop;
     
@@ -194,24 +200,24 @@ void DesktopIntegrationDialog::perform_desktop_integration()
     // iterate thru target_candidates to find icons folder
     for (size_t i = 0; i < target_candidates.size(); ++i) {
         // Copy icon PrusaSlicer.png from resources_dir()/icons to target_dir_icons/icons/
-        if (integrate_desktop_internal::contains_path_dir(target_candidates[i], "icons")) {
+        if (contains_path_dir(target_candidates[i], "icons")) {
             target_dir_icons = target_candidates[i];
             std::string icon_path = GUI::format("%1%/icons/PrusaSlicer.png",resources_dir());
             std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer%3%.png", target_dir_icons, icon_theme_path, version_suffix);
-            if (integrate_desktop_internal::copy_icon(icon_path, dest_path))
+            if (copy_icon(icon_path, dest_path))
                 break; // success
             else
                 target_dir_icons.clear(); // copying failed
             // if all failed - try creating default home folder
             if (i == target_candidates.size() - 1) {
                 // create $HOME/.local/share
-                integrate_desktop_internal::create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/icons" + icon_theme_dirs);
+                create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/icons" + icon_theme_dirs);
                 // copy icon
                 target_dir_icons = GUI::format("%1%/.local/share",wxFileName::GetHomeDir());
                 std::string icon_path = GUI::format("%1%/icons/PrusaSlicer.png",resources_dir());
                 std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer%3%.png", target_dir_icons, icon_theme_path, version_suffix);
-                if (!integrate_desktop_internal::contains_path_dir(target_dir_icons, "icons") 
-                    || !integrate_desktop_internal::copy_icon(icon_path, dest_path)) {
+                if (!contains_path_dir(target_dir_icons, "icons") 
+                    || !copy_icon(icon_path, dest_path)) {
                 	// every attempt failed - icon wont be present
                     target_dir_icons.clear(); 
                 }
@@ -228,7 +234,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
     // iterate thru target_candidates to find applications folder
     for (size_t i = 0; i < target_candidates.size(); ++i)
     {
-        if (integrate_desktop_internal::contains_path_dir(target_candidates[i], "applications")) {
+        if (contains_path_dir(target_candidates[i], "applications")) {
             target_dir_desktop = target_candidates[i];
             // Write slicer desktop file
             std::string desktop_file = GUI::format(
@@ -236,7 +242,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
                 "Name=PrusaSlicer%1%\n"
                 "GenericName=3D Printing Software\n"
                 "Icon=PrusaSlicer%2%\n"
-                "Exec=%3% %%F\n"
+                "Exec=\'%3%\' %%F\n"
                 "Terminal=false\n"
                 "Type=Application\n"
                 "MimeType=model/stl;application/vnd.ms-3mfdocument;application/prs.wavefront-obj;application/x-amf;\n"
@@ -246,23 +252,23 @@ void DesktopIntegrationDialog::perform_desktop_integration()
                 "StartupWMClass=prusa-slicer", name_suffix, version_suffix, appimage_path);
 
             std::string path = GUI::format("%1%/applications/PrusaSlicer%2%.desktop", target_dir_desktop, version_suffix);
-            if (integrate_desktop_internal::create_desktop_file(path, desktop_file)){
+            if (create_desktop_file(path, desktop_file)){
                 BOOST_LOG_TRIVIAL(debug) << "PrusaSlicer.desktop file installation success.";
                 break;
             } else {
             	// write failed - try another path
-                BOOST_LOG_TRIVIAL(error) << "PrusaSlicer.desktop file installation failed.";
+                BOOST_LOG_TRIVIAL(debug) << "Attempt to PrusaSlicer.desktop file installation failed. failed path: " << target_candidates[i];
                 target_dir_desktop.clear(); 
             }
             // if all failed - try creating default home folder
             if (i == target_candidates.size() - 1) {
                 // create $HOME/.local/share
-                integrate_desktop_internal::create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/applications");
+                create_path(boost::nowide::narrow(wxFileName::GetHomeDir()), ".local/share/applications");
                 // create desktop file
                 target_dir_desktop = GUI::format("%1%/.local/share",wxFileName::GetHomeDir());
                 std::string path = GUI::format("%1%/applications/PrusaSlicer%2%.desktop", target_dir_desktop, version_suffix);
-                if (integrate_desktop_internal::contains_path_dir(target_dir_desktop, "applications")) {
-                    if (!integrate_desktop_internal::create_desktop_file(path, desktop_file)) {    
+                if (contains_path_dir(target_dir_desktop, "applications")) {
+                    if (!create_desktop_file(path, desktop_file)) {    
                         // Desktop file not written - end desktop integration
                         BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not create desktop file";
                         return;
@@ -278,7 +284,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
     if(target_dir_desktop.empty()) {
     	// Desktop file not written - end desktop integration
         BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not find applications directory";
-        wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationFail);
+        show_error(nullptr, _L("Performing desktop integration failed - could not find applications directory."));
         return;
     }
     // save path to desktop file
@@ -290,7 +296,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
     {
     	std::string icon_path = GUI::format("%1%/icons/PrusaSlicer-gcodeviewer_192px.png",resources_dir());
 	    std::string dest_path = GUI::format("%1%/icons/%2%PrusaSlicer-gcodeviewer%3%.png", target_dir_icons, icon_theme_path, version_suffix);
-	    if (integrate_desktop_internal::copy_icon(icon_path, dest_path))
+	    if (copy_icon(icon_path, dest_path))
 	    	// save path to icon
 	        app_config->set("desktop_integration_icon_viewer_path", dest_path);
 	    else
@@ -303,7 +309,7 @@ void DesktopIntegrationDialog::perform_desktop_integration()
         "Name=Prusa Gcode Viewer%1%\n"
         "GenericName=3D Printing Software\n"
         "Icon=PrusaSlicer-gcodeviewer%2%\n"
-        "Exec=%3% --gcodeviwer %%F\n"
+        "Exec=\'%3%\' --gcodeviwer %%F\n"
         "Terminal=false\n"
         "Type=Application\n"
         "MimeType=text/x.gcode;\n"
@@ -312,23 +318,17 @@ void DesktopIntegrationDialog::perform_desktop_integration()
         "StartupNotify=false", name_suffix, version_suffix, appimage_path);
 
     std::string desktop_path = GUI::format("%1%/applications/PrusaSlicerGcodeViewer%2%.desktop", target_dir_desktop, version_suffix);
-    if (integrate_desktop_internal::create_desktop_file(desktop_path, desktop_file))
+    if (create_desktop_file(desktop_path, desktop_file))
     	// save path to desktop file
         app_config->set("desktop_integration_app_viewer_path", desktop_path);
     else {
-        BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could create gcode viewer desktop file";
-         wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationFail);
+        BOOST_LOG_TRIVIAL(error) << "Performing desktop integration failed - could not create Gcodeviewer desktop file";
+        show_error(nullptr, _L("Performing desktop integration failed - could not create Gcodeviewer desktop file. PrusaSlicer desktop file was probably created successfully."));
     }
     wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::DesktopIntegrationSuccess);
 }
 void DesktopIntegrationDialog::undo_desktop_intgration()
 {
-	const char *appimage_env = std::getenv("APPIMAGE");
-    if (!appimage_env) {
-        BOOST_LOG_TRIVIAL(error) << "Undo desktop integration failed - not Appimage executable.";
-    	wxGetApp().plater()->get_notification_manager()->push_notification(NotificationType::UndoDesktopIntegrationFail);
-        return;
-    }
     const AppConfig *app_config = wxGetApp().app_config;
     // slicer .desktop
     std::string path = std::string(app_config->get("desktop_integration_app_path"));
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index 91d16c602..06d805eeb 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -1806,10 +1806,10 @@ void GUI_App::add_config_menu(wxMenuBar *menu)
         local_menu->Append(config_id_base + ConfigMenuSnapshots, _L("&Configuration Snapshots") + dots, _L("Inspect / activate configuration snapshots"));
         local_menu->Append(config_id_base + ConfigMenuTakeSnapshot, _L("Take Configuration &Snapshot"), _L("Capture a configuration snapshot"));
         local_menu->Append(config_id_base + ConfigMenuUpdate, _L("Check for updates"), _L("Check for configuration updates"));
-#ifdef __linux__
-        if (DesktopIntegrationDialog::integration_possible())
-            local_menu->Append(config_id_base + ConfigMenuDesktopIntegration, _L("Desktop Integration"), _L("Desktop Integration"));    
-#endif        
+#if defined(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION) 
+        //if (DesktopIntegrationDialog::integration_possible())
+        local_menu->Append(config_id_base + ConfigMenuDesktopIntegration, _L("Desktop Integration"), _L("Desktop Integration"));    
+#endif //(__linux__) && defined(SLIC3R_DESKTOP_INTEGRATION)        
         local_menu->AppendSeparator();
     }
     local_menu->Append(config_id_base + ConfigMenuPreferences, _L("&Preferences") + dots +