diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3cd863f..251dab7 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,4 +1,53 @@
ci:
autoupdate_branch: "rewrite"
-repos: []
+repos:
+ - repo: https://github.com/Lucas-C/pre-commit-hooks
+ rev: v1.5.5
+ hooks:
+ - id: chmod
+ args: ["775"]
+ files: (\.sh|winapps)$
+ - id: forbid-crlf
+ - id: remove-crlf
+ - id: forbid-tabs
+ - id: remove-tabs
+ args: [--whitespaces-count, "2"]
+
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.6.0
+ hooks:
+ - id: check-added-large-files
+ - id: check-case-conflict
+ - id: check-executables-have-shebangs
+ - id: check-json
+ - id: check-merge-conflict
+ - id: check-shebang-scripts-are-executable
+ - id: check-symlinks
+ - id: check-toml
+ - id: check-vcs-permalinks
+ - id: check-xml
+ - id: check-yaml
+ - id: destroyed-symlinks
+ - id: detect-private-key
+ - id: end-of-file-fixer
+ - id: fix-byte-order-marker
+ - id: forbid-new-submodules
+ - id: forbid-submodules
+ - id: mixed-line-ending
+ - id: pretty-format-json
+ args: ["--autofix", "--no-sort-keys"]
+ - id: sort-simple-yaml
+ - id: trailing-whitespace
+
+ - repo: https://github.com/lovesegfault/beautysh
+ rev: v6.2.1
+ hooks:
+ - id: beautysh
+ additional_dependencies:
+ - setuptools
+
+ - repo: https://github.com/shellcheck-py/shellcheck-py
+ rev: v0.10.0.1
+ hooks:
+ - id: shellcheck
diff --git a/README.md b/README.md
index 2a59747..4e805fb 100644
--- a/README.md
+++ b/README.md
@@ -98,8 +98,8 @@ git clone https://github.com/winapps-org/winapps.git
cd winapps
```
-> [!note]
-> Ideally grab freerdp 3.0.0 or later, especially if you're having issues.
+> [!note]
+> Ideally grab freerdp 3.0.0 or later, especially if you're having issues.
> You can find nightly builds here: https://github.com/FreeRDP/FreeRDP/wiki/Prebuilds
### Step 3: Creating your WinApps configuration file
diff --git a/apps/acrobat-x-pro/icon.svg b/apps/acrobat-x-pro/icon.svg
old mode 100755
new mode 100644
diff --git a/apps/adobe-cc/icon.svg b/apps/adobe-cc/icon.svg
old mode 100755
new mode 100644
index 9272652..6c124a4
--- a/apps/adobe-cc/icon.svg
+++ b/apps/adobe-cc/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/adobe-cc/info b/apps/adobe-cc/info
index c8a0051..42a62ba 100644
--- a/apps/adobe-cc/info
+++ b/apps/adobe-cc/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES=""
# System Icon
-ICON="AdobeUpdate"
\ No newline at end of file
+ICON="AdobeUpdate"
diff --git a/apps/aftereffects-cc/icon.svg b/apps/aftereffects-cc/icon.svg
old mode 100755
new mode 100644
index 6b42dd7..677803b
--- a/apps/aftereffects-cc/icon.svg
+++ b/apps/aftereffects-cc/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/aftereffects-cc/info b/apps/aftereffects-cc/info
index 76a96be..7181324 100644
--- a/apps/aftereffects-cc/info
+++ b/apps/aftereffects-cc/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES="application/vnd.adobe.aftereffects.project;application/vnd.adobe.aftereffects.template;"
# System Icon
-ICON="AdobeAfterEffect"
\ No newline at end of file
+ICON="AdobeAfterEffect"
diff --git a/apps/audition-cc/icon.svg b/apps/audition-cc/icon.svg
old mode 100755
new mode 100644
index 01c32a6..af88949
--- a/apps/audition-cc/icon.svg
+++ b/apps/audition-cc/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/audition-cc/info b/apps/audition-cc/info
index 934abc3..b3bdde4 100644
--- a/apps/audition-cc/info
+++ b/apps/audition-cc/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES=""
# System Icon
-ICON="AdobeAudition"
\ No newline at end of file
+ICON="AdobeAudition"
diff --git a/apps/bridge-cc/icon.svg b/apps/bridge-cc/icon.svg
old mode 100755
new mode 100644
index 6a84294..6fd0faa
--- a/apps/bridge-cc/icon.svg
+++ b/apps/bridge-cc/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/bridge-cc/info b/apps/bridge-cc/info
index 02edf53..b4a8f09 100644
--- a/apps/bridge-cc/info
+++ b/apps/bridge-cc/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES="image/vnd.adobe.photoshop;"
# System Icon
-ICON="AdobeBridge"
\ No newline at end of file
+ICON="AdobeBridge"
diff --git a/apps/bridge-cs6-x86/icon.svg b/apps/bridge-cs6-x86/icon.svg
old mode 100755
new mode 100644
index 6a84294..6fd0faa
--- a/apps/bridge-cs6-x86/icon.svg
+++ b/apps/bridge-cs6-x86/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/bridge-cs6-x86/info b/apps/bridge-cs6-x86/info
index eaaa69a..1d8cf59 100644
--- a/apps/bridge-cs6-x86/info
+++ b/apps/bridge-cs6-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES="image/vnd.adobe.photoshop;"
# System Icon
-ICON="AdobeBridge"
\ No newline at end of file
+ICON="AdobeBridge"
diff --git a/apps/bridge-cs6/icon.svg b/apps/bridge-cs6/icon.svg
old mode 100755
new mode 100644
index 6a84294..6fd0faa
--- a/apps/bridge-cs6/icon.svg
+++ b/apps/bridge-cs6/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/bridge-cs6/info b/apps/bridge-cs6/info
index 66b29fc..3fa52e8 100644
--- a/apps/bridge-cs6/info
+++ b/apps/bridge-cs6/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES="image/vnd.adobe.photoshop;"
# System Icon
-ICON="AdobeBridge"
\ No newline at end of file
+ICON="AdobeBridge"
diff --git a/apps/cmd/info b/apps/cmd/info
index af457af..08e2e87 100644
--- a/apps/cmd/info
+++ b/apps/cmd/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Windows"
MIME_TYPES=""
# System Icon
-ICON="Terminal"
\ No newline at end of file
+ICON="Terminal"
diff --git a/apps/excel-o365-x86/info b/apps/excel-o365-x86/info
index e50b961..94b8372 100644
--- a/apps/excel-o365-x86/info
+++ b/apps/excel-o365-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.ms-excel.sheet.macroEnabled.12;application/vnd.ms-excel.template.macroEnabled.12;application/vnd.ms-excel.addin.macroEnabled.12;application/vnd.ms-excel.sheet.binary.macroEnabled.12;"
# System Icon
-ICON="ms-excel"s
\ No newline at end of file
+ICON="ms-excel"s
diff --git a/apps/excel-o365/info b/apps/excel-o365/info
index 9671c74..e0e67e5 100644
--- a/apps/excel-o365/info
+++ b/apps/excel-o365/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.ms-excel.sheet.macroEnabled.12;application/vnd.ms-excel.template.macroEnabled.12;application/vnd.ms-excel.addin.macroEnabled.12;application/vnd.ms-excel.sheet.binary.macroEnabled.12;"
# System Icon
-ICON="ms-excel"
\ No newline at end of file
+ICON="ms-excel"
diff --git a/apps/excel-x86/info b/apps/excel-x86/info
index 5a71f70..bfdb56a 100644
--- a/apps/excel-x86/info
+++ b/apps/excel-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.ms-excel.sheet.macroEnabled.12;application/vnd.ms-excel.template.macroEnabled.12;application/vnd.ms-excel.addin.macroEnabled.12;application/vnd.ms-excel.sheet.binary.macroEnabled.12;"
# System Icon
-ICON="ms-excel"
\ No newline at end of file
+ICON="ms-excel"
diff --git a/apps/excel/info b/apps/excel/info
index ad891ff..9ef5cb4 100644
--- a/apps/excel/info
+++ b/apps/excel/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-excel;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.spreadsheetml.template;application/vnd.ms-excel.sheet.macroEnabled.12;application/vnd.ms-excel.template.macroEnabled.12;application/vnd.ms-excel.addin.macroEnabled.12;application/vnd.ms-excel.sheet.binary.macroEnabled.12;"
# System Icon
-ICON="ms-excel"
\ No newline at end of file
+ICON="ms-excel"
diff --git a/apps/illustrator-cc/icon.svg b/apps/illustrator-cc/icon.svg
old mode 100755
new mode 100644
index 7ea299b..21d31b3
--- a/apps/illustrator-cc/icon.svg
+++ b/apps/illustrator-cc/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/illustrator-cc/info b/apps/illustrator-cc/info
index c8ba5da..58af241 100644
--- a/apps/illustrator-cc/info
+++ b/apps/illustrator-cc/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES="application/illustrator;"
# System Icon
-ICON="AdobeIllustrator"
\ No newline at end of file
+ICON="AdobeIllustrator"
diff --git a/apps/indesign-cc/icon.svg b/apps/indesign-cc/icon.svg
old mode 100755
new mode 100644
index f26dead..ceaa431
--- a/apps/indesign-cc/icon.svg
+++ b/apps/indesign-cc/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/indesign-cc/info b/apps/indesign-cc/info
index b60a80e..481b2dc 100644
--- a/apps/indesign-cc/info
+++ b/apps/indesign-cc/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES="application/x-adobe-indesign-interchange;application/x-adobe-indesign;"
# System Icon
-ICON="AdobeIndesign"
\ No newline at end of file
+ICON="AdobeIndesign"
diff --git a/apps/lightroom-cc/icon.svg b/apps/lightroom-cc/icon.svg
old mode 100755
new mode 100644
index 9a02e00..6d10ba7
--- a/apps/lightroom-cc/icon.svg
+++ b/apps/lightroom-cc/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/lightroom-cc/info b/apps/lightroom-cc/info
index 23ef96b..a2cdb25 100644
--- a/apps/lightroom-cc/info
+++ b/apps/lightroom-cc/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES=""
# System Icon
-ICON="AdobeLightroom"
\ No newline at end of file
+ICON="AdobeLightroom"
diff --git a/apps/onenote-o365-x86/icon.svg b/apps/onenote-o365-x86/icon.svg
index b76f325..cf85277 100644
--- a/apps/onenote-o365-x86/icon.svg
+++ b/apps/onenote-o365-x86/icon.svg
@@ -1,3 +1,3 @@
\ No newline at end of file
+
diff --git a/apps/onenote-o365-x86/info b/apps/onenote-o365-x86/info
index 1ce4872..335e780 100644
--- a/apps/onenote-o365-x86/info
+++ b/apps/onenote-o365-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/msonenote;"
# System Icon
-ICON="ms-outlook"
\ No newline at end of file
+ICON="ms-outlook"
diff --git a/apps/onenote-o365/icon.svg b/apps/onenote-o365/icon.svg
index b76f325..cf85277 100644
--- a/apps/onenote-o365/icon.svg
+++ b/apps/onenote-o365/icon.svg
@@ -1,3 +1,3 @@
\ No newline at end of file
+
diff --git a/apps/onenote-o365/info b/apps/onenote-o365/info
index 248fea3..6626816 100644
--- a/apps/onenote-o365/info
+++ b/apps/onenote-o365/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/msonenote;"
# System Icon
-ICON="ms-outlook"
\ No newline at end of file
+ICON="ms-outlook"
diff --git a/apps/onenote-x86/icon.svg b/apps/onenote-x86/icon.svg
index b76f325..cf85277 100644
--- a/apps/onenote-x86/icon.svg
+++ b/apps/onenote-x86/icon.svg
@@ -1,3 +1,3 @@
\ No newline at end of file
+
diff --git a/apps/onenote-x86/info b/apps/onenote-x86/info
index cf68779..e535123 100644
--- a/apps/onenote-x86/info
+++ b/apps/onenote-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/msonenote;"
# System Icon
-ICON="ms-onenote"
\ No newline at end of file
+ICON="ms-onenote"
diff --git a/apps/onenote/icon.svg b/apps/onenote/icon.svg
index b76f325..cf85277 100644
--- a/apps/onenote/icon.svg
+++ b/apps/onenote/icon.svg
@@ -1,3 +1,3 @@
\ No newline at end of file
+
diff --git a/apps/onenote/info b/apps/onenote/info
index d6e6636..908f58e 100644
--- a/apps/onenote/info
+++ b/apps/onenote/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/msonenote;"
# System Icon
-ICON="ms-outlook"
\ No newline at end of file
+ICON="ms-outlook"
diff --git a/apps/outlook-o365-x86/info b/apps/outlook-o365-x86/info
index 31f5746..9a528f4 100644
--- a/apps/outlook-o365-x86/info
+++ b/apps/outlook-o365-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-outlook;application/octet-stream;"
# System Icon
-ICON="ms-outlook"
\ No newline at end of file
+ICON="ms-outlook"
diff --git a/apps/outlook-o365/info b/apps/outlook-o365/info
index f248cab..4763b83 100644
--- a/apps/outlook-o365/info
+++ b/apps/outlook-o365/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-outlook;application/octet-stream;"
# System Icon
-ICON="ms-outlook"
\ No newline at end of file
+ICON="ms-outlook"
diff --git a/apps/outlook-x86/info b/apps/outlook-x86/info
index 9f68b8e..4874db3 100644
--- a/apps/outlook-x86/info
+++ b/apps/outlook-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-outlook;application/octet-stream;"
# System Icon
-ICON="ms-outlook"
\ No newline at end of file
+ICON="ms-outlook"
diff --git a/apps/outlook/info b/apps/outlook/info
index d990949..43453c6 100644
--- a/apps/outlook/info
+++ b/apps/outlook/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-outlook;application/octet-stream;"
# System Icon
-ICON="ms-outlook"
\ No newline at end of file
+ICON="ms-outlook"
diff --git a/apps/photoshop-cc/icon.svg b/apps/photoshop-cc/icon.svg
index a9d19f7..9565f6d 100644
--- a/apps/photoshop-cc/icon.svg
+++ b/apps/photoshop-cc/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/photoshop-cc/info b/apps/photoshop-cc/info
index 8f8a220..a7413d6 100644
--- a/apps/photoshop-cc/info
+++ b/apps/photoshop-cc/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES="image/vnd.adobe.photoshop;"
# System Icon
-ICON="AdobePhotoshop"
\ No newline at end of file
+ICON="AdobePhotoshop"
diff --git a/apps/photoshop-cs6-x86/icon.svg b/apps/photoshop-cs6-x86/icon.svg
index a9d19f7..9565f6d 100644
--- a/apps/photoshop-cs6-x86/icon.svg
+++ b/apps/photoshop-cs6-x86/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/photoshop-cs6-x86/info b/apps/photoshop-cs6-x86/info
index 2a23552..16d8911 100644
--- a/apps/photoshop-cs6-x86/info
+++ b/apps/photoshop-cs6-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES="image/vnd.adobe.photoshop;"
# System Icon
-ICON="AdobePhotoshop"
\ No newline at end of file
+ICON="AdobePhotoshop"
diff --git a/apps/photoshop-cs6/icon.svg b/apps/photoshop-cs6/icon.svg
index a9d19f7..9565f6d 100644
--- a/apps/photoshop-cs6/icon.svg
+++ b/apps/photoshop-cs6/icon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
diff --git a/apps/photoshop-cs6/info b/apps/photoshop-cs6/info
index bc1d939..24cb454 100644
--- a/apps/photoshop-cs6/info
+++ b/apps/photoshop-cs6/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Adobe"
MIME_TYPES="image/vnd.adobe.photoshop;"
# System Icon
-ICON="AdobePhotoshop"
\ No newline at end of file
+ICON="AdobePhotoshop"
diff --git a/apps/powerpoint-o365-x86/info b/apps/powerpoint-o365-x86/info
index 9c89d89..755acc6 100644
--- a/apps/powerpoint-o365-x86/info
+++ b/apps/powerpoint-o365-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.presentationml.slideshow;application/vnd.ms-powerpoint.addin.macroEnabled.12;application/vnd.ms-powerpoint.presentation.macroEnabled.12;application/vnd.ms-powerpoint.template.macroEnabled.12;application/vnd.ms-powerpoint.slideshow.macroEnabled.12;"
# System Icon
-ICON="ms-powerpoint"
\ No newline at end of file
+ICON="ms-powerpoint"
diff --git a/apps/powerpoint-o365/info b/apps/powerpoint-o365/info
index ce16e08..a0d25d2 100644
--- a/apps/powerpoint-o365/info
+++ b/apps/powerpoint-o365/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.presentationml.slideshow;application/vnd.ms-powerpoint.addin.macroEnabled.12;application/vnd.ms-powerpoint.presentation.macroEnabled.12;application/vnd.ms-powerpoint.template.macroEnabled.12;application/vnd.ms-powerpoint.slideshow.macroEnabled.12;"
# System Icon
-ICON="ms-powerpoint"
\ No newline at end of file
+ICON="ms-powerpoint"
diff --git a/apps/powerpoint-x86/info b/apps/powerpoint-x86/info
index 409318f..21ba721 100644
--- a/apps/powerpoint-x86/info
+++ b/apps/powerpoint-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.presentationml.slideshow;application/vnd.ms-powerpoint.addin.macroEnabled.12;application/vnd.ms-powerpoint.presentation.macroEnabled.12;application/vnd.ms-powerpoint.template.macroEnabled.12;application/vnd.ms-powerpoint.slideshow.macroEnabled.12;"
# System Icon
-ICON="ms-powerpoint"
\ No newline at end of file
+ICON="ms-powerpoint"
diff --git a/apps/powerpoint/info b/apps/powerpoint/info
index e08c80d..6910809 100644
--- a/apps/powerpoint/info
+++ b/apps/powerpoint/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/vnd.ms-powerpoint;application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.template;application/vnd.openxmlformats-officedocument.presentationml.slideshow;application/vnd.ms-powerpoint.addin.macroEnabled.12;application/vnd.ms-powerpoint.presentation.macroEnabled.12;application/vnd.ms-powerpoint.template.macroEnabled.12;application/vnd.ms-powerpoint.slideshow.macroEnabled.12;"
# System Icon
-ICON="ms-powerpoint"
\ No newline at end of file
+ICON="ms-powerpoint"
diff --git a/apps/publisher-o365-x86/icon.svg b/apps/publisher-o365-x86/icon.svg
index 6706891..82b310e 100644
--- a/apps/publisher-o365-x86/icon.svg
+++ b/apps/publisher-o365-x86/icon.svg
@@ -1,3 +1,3 @@
diff --git a/apps/publisher-o365/icon.svg b/apps/publisher-o365/icon.svg
index 6706891..82b310e 100644
--- a/apps/publisher-o365/icon.svg
+++ b/apps/publisher-o365/icon.svg
@@ -1,3 +1,3 @@
diff --git a/apps/publisher-x86/icon.svg b/apps/publisher-x86/icon.svg
index 6706891..82b310e 100644
--- a/apps/publisher-x86/icon.svg
+++ b/apps/publisher-x86/icon.svg
@@ -1,3 +1,3 @@
diff --git a/apps/publisher/icon.svg b/apps/publisher/icon.svg
index 6706891..82b310e 100644
--- a/apps/publisher/icon.svg
+++ b/apps/publisher/icon.svg
@@ -1,3 +1,3 @@
diff --git a/apps/word-o365-x86/info b/apps/word-o365-x86/info
index 8a3011a..b2d853d 100644
--- a/apps/word-o365-x86/info
+++ b/apps/word-o365-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/msword;application/vnd.openxmlformats-officedocument.wordprocessingml.document;application/vnd.openxmlformats-officedocument.wordprocessingml.template;application/vnd.ms-word.document.macroEnabled.12;application/vnd.ms-word.template.macroEnabled.12;"
# System Icon
-ICON="ms-word"
\ No newline at end of file
+ICON="ms-word"
diff --git a/apps/word-o365/info b/apps/word-o365/info
index 4223a4d..0632b79 100644
--- a/apps/word-o365/info
+++ b/apps/word-o365/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/msword;application/vnd.openxmlformats-officedocument.wordprocessingml.document;application/vnd.openxmlformats-officedocument.wordprocessingml.template;application/vnd.ms-word.document.macroEnabled.12;application/vnd.ms-word.template.macroEnabled.12;"
# System Icon
-ICON="ms-word"
\ No newline at end of file
+ICON="ms-word"
diff --git a/apps/word-x86/info b/apps/word-x86/info
index ffe7a81..b35c54e 100644
--- a/apps/word-x86/info
+++ b/apps/word-x86/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/msword;application/vnd.openxmlformats-officedocument.wordprocessingml.document;application/vnd.openxmlformats-officedocument.wordprocessingml.template;application/vnd.ms-word.document.macroEnabled.12;application/vnd.ms-word.template.macroEnabled.12;"
# System Icon
-ICON="ms-word"
\ No newline at end of file
+ICON="ms-word"
diff --git a/apps/word/info b/apps/word/info
index 62b6774..a1dfd71 100644
--- a/apps/word/info
+++ b/apps/word/info
@@ -14,4 +14,4 @@ CATEGORIES="WinApps;Office"
MIME_TYPES="application/msword;application/vnd.openxmlformats-officedocument.wordprocessingml.document;application/vnd.openxmlformats-officedocument.wordprocessingml.template;application/vnd.ms-word.document.macroEnabled.12;application/vnd.ms-word.template.macroEnabled.12;"
# System Icon
-ICON="ms-word"
\ No newline at end of file
+ICON="ms-word"
diff --git a/bin/winapps b/bin/winapps
index 03bd9e7..fdfc653 100755
--- a/bin/winapps
+++ b/bin/winapps
@@ -1,123 +1,130 @@
#!/usr/bin/env bash
-if [ ! -f "${HOME}/.config/winapps/winapps.conf" ] && [ ! -f "${HOME}/.winapps" ]; then
- echo "You need to create a ~/.config/winapps/winapps.conf configuration. Exiting..."
- exit
+if [ ! -f "$HOME/.config/winapps/winapps.conf" ] && [ ! -f "$HOME/.winapps" ]; then
+ echo "You need to create a ~/.config/winapps/winapps.conf configuration. Exiting..."
+ exit
fi
DIR="$(dirname "$(readlink -f "$0")")"
-RUN="$(date)-${RANDOM}"
+RUN="$(date)-$RANDOM"
-if [ ! -d "${HOME}/.local/share/winapps" ]; then
- mkdir -p "${HOME}/.local/share/winapps"
+if [ ! -d "$HOME/.local/share/winapps" ]; then
+ mkdir -p "$HOME/.local/share/winapps"
fi
RDP_SCALE=100
-if [ -f "${HOME}/.config/winapps/winapps.conf" ]; then
- . "${HOME}/.config/winapps/winapps.conf"
+if [ -f "$HOME/.config/winapps/winapps.conf" ]; then
+ # shellcheck source=/dev/null
+ . "$HOME/.config/winapps/winapps.conf"
else
- . "${HOME}/.winapps"
+ # shellcheck source=/dev/null
+ . "$HOME/.winapps"
fi
function dprint() {
- if [ "${DEBUG}" = "true" ]; then
- echo "[${RUN}] ${1}" >>"${HOME}/.local/share/winapps/winapps.log"
- fi
+ if [ "$DEBUG" = "true" ]; then
+ echo "[$RUN] $1" >>"$HOME/.local/share/winapps/winapps.log"
+ fi
}
dprint "START"
-if [ -f "${HOME}/.local/share/winapps/run" ]; then
- LAST_RAN=$(stat -t -c %Y "${HOME}/.local/share/winapps/run")
- dprint "LAST_RAN:${LAST_RAN}"
- touch "${HOME}/.local/share/winapps/run"
- THIS_RUN=$(stat -t -c %Y "${HOME}/.local/share/winapps/run")
- dprint "THIS_RUN:${THIS_RUN}"
- if ((THIS_RUN - LAST_RAN < 2)); then
- exit
- fi
+if [ -f "$HOME/.local/share/winapps/run" ]; then
+ LAST_RAN=$(stat -t -c %Y "$HOME/.local/share/winapps/run")
+ dprint "LAST_RAN:${LAST_RAN}"
+ touch "$HOME/.local/share/winapps/run"
+ THIS_RUN=$(stat -t -c %Y "$HOME/.local/share/winapps/run")
+ dprint "THIS_RUN:$THIS_RUN"
+ if ((THIS_RUN - LAST_RAN < 2)); then
+ exit
+ fi
else
- touch "${HOME}/.local/share/winapps/run"
+ touch "$HOME/.local/share/winapps/run"
fi
if [ -z "${FREERDP_COMMAND}" ]; then
- if command -v xfreerdp &> /dev/null
- then
- FREERDP_COMMAND="xfreerdp"
- elif command -v xfreerdp3 &> /dev/null
- then
- FREERDP_COMMAND="xfreerdp3"
- fi
-elif command -v $FREERDP_COMMAND &> /dev/null
+ if command -v xfreerdp &> /dev/null
+ then
+ FREERDP_COMMAND="xfreerdp"
+ elif command -v xfreerdp3 &> /dev/null
+ then
+ FREERDP_COMMAND="xfreerdp3"
+ fi
+elif command -v "$FREERDP_COMMAND" &> /dev/null
then
- dprint "Using custom freerdp command ${FREERDP_COMMAND}"
+ dprint "Using custom freerdp command $FREERDP_COMMAND"
else
- echo "You have supplied a custom FreeRDP command, but the command is not available."
- exit
+ echo "You have supplied a custom FreeRDP command, but the command is not available."
+ exit
fi
-if [ -z "${RDP_IP}" ]; then
- if [ ! "$(groups | grep -v libvirt)" ]; then
- echo "You are not a member of the libvirt group. Run the below then reboot."
- echo ' sudo usermod -a -G libvirt $(whoami)'
- echo ' sudo usermod -a -G kvm $(whoami)'
- exit
- fi
- if [ ! "$(virsh list | grep -v RDPWindows)" ]; then
- echo "RDPWindows is not running, run:"
- echo " virsh start RDPWindows"
- exit
- fi
- RDP_IP=$(virsh net-dhcp-leases default | grep RDPWindows | awk '{print $5}')
- RDP_IP=${RDP_IP%%\/*}
+if [ -z "$RDP_IP" ]; then
+ if groups | grep -vq libvirt; then
+ echo "You are not a member of the libvirt group. Run the below then reboot."
+ echo " sudo usermod -a -G libvirt $(whoami)"
+ echo " sudo usermod -a -G kvm $(whoami)"
+ exit
+ fi
+ if virsh list | grep -vq RDPWindows; then
+ echo "RDPWindows is not running, run:"
+ echo " virsh start RDPWindows"
+ exit
+ fi
+ RDP_IP=$(virsh net-dhcp-leases default | grep RDPWindows | awk '{print $5}')
+ RDP_IP=${RDP_IP%%\/*}
fi
-dprint "1:${1}"
-dprint "2:${2}"
+dprint "1:$1"
+dprint "2:$2"
# this is just for debug logging anyways
# shellcheck disable=SC2145
dprint "@:${@}"
MULTI_FLAG="+span"
-if [ "${MULTIMON}" = "true" ]; then
- MULTI_FLAG="/multimon"
+if [ "$MULTIMON" = "true" ]; then
+ MULTI_FLAG="/multimon"
fi
-if [ "${1}" = "windows" ]; then
- $FREERDP_COMMAND ${RDP_FLAGS} /d:"${RDP_DOMAIN}" /u:"${RDP_USER}" /p:"${RDP_PASS}" /scale:${RDP_SCALE} +dynamic-resolution +auto-reconnect +home-drive /wm-class:"Microsoft Windows" /v:${RDP_IP} 1>/dev/null 2>&1 &
-elif [ "${1}" = "check" ]; then
- dprint "CHECK"
- $FREERDP_COMMAND ${RDP_FLAGS} /d:"${RDP_DOMAIN}" /u:"${RDP_USER}" /p:"${RDP_PASS}" /scale:${RDP_SCALE} +auto-reconnect +home-drive -wallpaper +dynamic-resolution ${MULTI_FLAG} /app:program:"explorer.exe" /v:${RDP_IP}
-elif [ "${1}" = "manual" ]; then
- dprint "MANUAL:${2}"
- $FREERDP_COMMAND ${RDP_FLAGS} /d:"${RDP_DOMAIN}" /u:"${RDP_USER}" /p:"${RDP_PASS}" /scale:${RDP_SCALE} +auto-reconnect +home-drive +dynamic-resolution ${MULTI_FLAG} /app:program:"${2}" /v:"${RDP_IP}" 1>/dev/null 2>&1 &
-elif [ "${1}" != "install" ]; then
- dprint "DIR:${DIR}"
- if [ -e "${DIR}/../apps/${1}/info" ]; then
- # shellcheck disable=SC1090
- . "${DIR}/../apps/${1}/info"
- ICON="${DIR}/../apps/${1}/icon.svg"
- elif [ -e "${HOME}/.local/share/winapps/apps/${1}/info" ]; then
- # shellcheck disable=SC1090
- . "${HOME}/.local/share/winapps/apps/${1}/info"
- ICON="${HOME}/.local/share/winapps/apps/${1}/icon.svg"
- elif [ -e "/usr/local/share/winapps/apps/${1}/info" ]; then
- # shellcheck disable=SC1090
- . "/usr/local/share/winapps/apps/${1}/info"
- ICON="/usr/local/share/winapps/apps/${1}/icon.svg"
- else
- echo "You need to run 'installer.sh' first."
- exit 1
- fi
- if [ -n "${2}" ]; then
- dprint "HOME:${HOME}"
- FILE=$(echo "${2}" | sed 's|'"${HOME}"'|\\\\tsclient\\home|;s|/|\\|g;s|\\|\\\\|g')
- dprint "FILE:${FILE}"
- $FREERDP_COMMAND ${RDP_FLAGS} /d:"${RDP_DOMAIN}" /u:"${RDP_USER}" /p:"${RDP_PASS}" /scale:${RDP_SCALE} +auto-reconnect +clipboard +home-drive -wallpaper +dynamic-resolution ${MULTI_FLAG} /wm-class:"${FULL_NAME}" /app:program:"${WIN_EXECUTABLE}",icon:"${ICON}",name:"${FULL_NAME}",cmd:"\"$FILE\"" /v:"${RDP_IP}" 1>/dev/null 2>&1 &
- else
- $FREERDP_COMMAND ${RDP_FLAGS} /d:"${RDP_DOMAIN}" /u:"${RDP_USER}" /p:"${RDP_PASS}" /scale:${RDP_SCALE} +auto-reconnect +clipboard +home-drive -wallpaper +dynamic-resolution ${MULTI_FLAG} /wm-class:"${FULL_NAME}" /app:program:"${WIN_EXECUTABLE}",icon:"${ICON}",name:"${FULL_NAME}" /v:"${RDP_IP}" 1>/dev/null 2>&1 &
- fi
+if [[ -n "$RDP_FLAGS" ]]; then
+ FREERDP_COMMAND="$FREERDP_COMMAND $RDP_FLAGS"
+fi
+
+if [ "$1" = "windows" ]; then
+ $FREERDP_COMMAND /d:"$RDP_DOMAIN" /u:"$RDP_USER" /p:"$RDP_PASS" /scale:$RDP_SCALE +dynamic-resolution +auto-reconnect +home-drive /wm-class:"Microsoft Windows" /v:"$RDP_IP" 1>/dev/null 2>&1 &
+elif [ "$1" = "check" ]; then
+ dprint "CHECK"
+ $FREERDP_COMMAND /d:"$RDP_DOMAIN" /u:"$RDP_USER" /p:"$RDP_PASS" /scale:$RDP_SCALE +auto-reconnect +home-drive -wallpaper +dynamic-resolution $MULTI_FLAG /app:program:"explorer.exe" /v:"$RDP_IP"
+elif [ "$1" = "manual" ]; then
+ dprint "MANUAL:$2"
+ $FREERDP_COMMAND /d:"$RDP_DOMAIN" /u:"$RDP_USER" /p:"$RDP_PASS" /scale:$RDP_SCALE +auto-reconnect +home-drive +dynamic-resolution $MULTI_FLAG /app:program:"$2" /v:"$RDP_IP" 1>/dev/null 2>&1 &
+elif [ "$1" != "install" ]; then
+ dprint "DIR:${DIR}"
+ if [ -e "${DIR}/../apps/$1/info" ]; then
+ # shellcheck disable=SC1090
+ . "${DIR}/../apps/$1/info"
+ ICON="${DIR}/../apps/$1/icon.svg"
+ elif [ -e "$HOME/.local/share/winapps/apps/$1/info" ]; then
+ # shellcheck disable=SC1090
+ . "$HOME/.local/share/winapps/apps/$1/info"
+ ICON="$HOME/.local/share/winapps/apps/$1/icon.svg"
+ elif [ -e "/usr/local/share/winapps/apps/$1/info" ]; then
+ # shellcheck disable=SC1090
+ . "/usr/local/share/winapps/apps/$1/info"
+ ICON="/usr/local/share/winapps/apps/$1/icon.svg"
+ else
+ echo "You need to run 'installer.sh' first."
+ exit 1
+ fi
+ if [ -n "$2" ]; then
+ dprint "HOME:$HOME"
+ FILE=$(echo "$2" | sed 's|'"$HOME"'|\\\\tsclient\\home|;s|/|\\|g;s|\\|\\\\|g')
+ dprint "FILE:${FILE}"
+ # shellcheck disable=SC2140
+ $FREERDP_COMMAND /d:"$RDP_DOMAIN" /u:"$RDP_USER" /p:"$RDP_PASS" /scale:$RDP_SCALE +auto-reconnect +clipboard +home-drive -wallpaper +dynamic-resolution $MULTI_FLAG /wm-class:"$FULL_NAME" /app:program:"$WIN_EXECUTABLE",icon:"$ICON",name:"$FULL_NAME",cmd:"\"$FILE\"" /v:"$RDP_IP" 1>/dev/null 2>&1 &
+ else
+ $FREERDP_COMMAND /d:"$RDP_DOMAIN" /u:"$RDP_USER" /p:"$RDP_PASS" /scale:$RDP_SCALE +auto-reconnect +clipboard +home-drive -wallpaper +dynamic-resolution $MULTI_FLAG /wm-class:"$FULL_NAME" /app:program:"$WIN_EXECUTABLE",icon:"$ICON",name:"$FULL_NAME" /v:"$RDP_IP" 1>/dev/null 2>&1 &
+ fi
fi
dprint "END"
diff --git a/compose.yaml b/compose.yaml
new file mode 100644
index 0000000..9599920
--- /dev/null
+++ b/compose.yaml
@@ -0,0 +1,23 @@
+name: "winapps"
+
+volumes:
+ data:
+
+services:
+ windows:
+ image: dockurr/windows
+ container_name: windows
+ environment:
+ VERSION: "tiny11"
+ RAM_SIZE: "4G"
+ CPU_CORES: "4"
+ privileged: true
+ ports:
+ - 8006:8006
+ - 3389:3389/tcp
+ - 3389:3389/udp
+ stop_grace_period: 2m
+ restart: on-failure
+ volumes:
+ - data:/storage
+ - ./oem:/oem
diff --git a/docs/KVM.md b/docs/KVM.md
index dea6e93..ea65b27 100644
--- a/docs/KVM.md
+++ b/docs/KVM.md
@@ -198,6 +198,3 @@ sudo systemctl restart libvirtd
sudo ln -s /etc/apparmor.d/usr.sbin.libvirtd /etc/apparmor.d/disable/
```
You will likely need to reboot to ensure your current shell is added to the group.
-
-
-
diff --git a/docs/docker.md b/docs/docker.md
index 9c84a6e..501e49b 100644
--- a/docs/docker.md
+++ b/docs/docker.md
@@ -1,81 +1,83 @@
-# Docker
-
-## Why docker?
-
-While working with virsh is completely fine for winapps, however you have to setup and optimise you vm manually. Docker on the other hand setups most of the stuff automatically and also makes the vm highly portable between linux distros.
-
-# Requirements
-
-Since docker manages the dependencies of the container automatically you only need to install docker or podman itself. (Podman is recommended because of the faster container startup times. Note that podman and docker are interchangeable so no instructions will change depending on which one you use)
-
-You might also want to take a look in the docs:
-- [podman docs](https://docs.podman.io/)
-- [docker docs](https://docs.docker.com/)
-
-When using podman you want to make sure podman socket is enabled with:
-```shell
-sudo systemctl enable --now podman.socket
-```
-
-> [!NOTE]
-> This will only work on linux systems since some kernel interfaces (like kvm) are needed by the vm. Because of this performance can vary in kernel versions (newer will likely perform better).
-
-# Setup docker container
-
-The easiest way to setup a windows vm is by using docker compose. Just create a `compose.yml` with following content:
-
-```yaml
-name: "winapps"
-
-volumes:
- data:
-
-services:
- windows:
- image: dockurr/windows
- container_name: windows
- environment:
- VERSION: "tiny11"
- RAM_SIZE: "4G"
- CPU_CORES: "4"
- privileged: true
- ports:
- - 8006:8006
- - 3389:3389/tcp
- - 3389:3389/udp
- stop_grace_period: 2m
- restart: on-failure
- volumes:
- - data:/storage
-```
-
-Now you can tune the ram/usage by changing RAM_SIZE/CPU_CORES. You can also specify the windows versions you want to use. You might also want to take a look at the [docker image repo](https://github.com/dockur/windows).
-
-> [!NOTE]
-> Older versions than Windows 10 are not officially supported. However they might still work with some additional tuning.
-
-You can now just run:
-```shell
-docker compose up
-```
-
-After this just open http://127.0.0.1:8006 in your webbrowser and finish you windows installation as usual.
-
-> [!WARNING]
-> Change the RDP_IP in your winapps config to localhost or "127.0.0.1".
+# Docker
-> [!WARNING]
-> RDP will be automatically enabled, however you still need to load the [reg file](https://github.com/winapps-org/winapps/blob/main/install%2FRDPApps.reg) into you vm.
-> Just use a browser inside the vm to download.
-
-Now you should be ready to go and try to connect to your vm with winapps.
-
-For stopping the vm just use:
-```shell
-docker compose stop
-```
-
-For starting again afterwards use:
-```shell
-docker compose start
-```
+## Why docker?
+
+While working with `virsh` is completely fine for winapps, you have to set up and optimize you vm manually. Docker on the other hand sets up most of the stuff automatically and also makes the VM highly portable between Linux distros.
+
+# Requirements
+
+Since Docker manages the dependencies of the container automatically you only need to install Docker itself.
+
+You can try using Podman too because of their faster container startup times, but note that Podman and Docker are not always fully interchangeable. In case you want to follow this guide using podman, you will have to install the `docker` CLI to be able to run `docker compose` commands. You'll also have to enable the Podman socket. Refer to the podman docs for how to do that.
+
+See:
+- [Podman installation docs](https://podman.io/docs/installation)
+- [Docker installation docs](https://docs.docker.com/engine/install)
+- [Using `docker compose` with Podman](https://www.redhat.com/sysadmin/podman-docker-compose) (slightly outdated)
+
+> [!NOTE]
+> This will only work on Linux systems since some kernel interfaces (like KVM) are needed by the VM. Because of this performance can vary depending on kernel version (newer will likely perform better).
+
+# Setup docker container
+
+The easiest way to set up a Windows VM is by using docker compose. A compose file that looks like this is already shipped with winapps:
+
+```yaml
+name: "winapps"
+
+volumes:
+ data:
+
+services:
+ windows:
+ image: dockurr/windows
+ container_name: windows
+ environment:
+ VERSION: "tiny11"
+ RAM_SIZE: "4G"
+ CPU_CORES: "4"
+ privileged: true
+ ports:
+ - 8006:8006
+ - 3389:3389/tcp
+ - 3389:3389/udp
+ stop_grace_period: 2m
+ restart: on-failure
+ volumes:
+ - data:/storage
+```
+
+Now you can tune the ram/usage by changing `RAM_SIZE` & `CPU_CORES`. You can also specify the windows versions you want to use. You might also want to take a look at the [repo of the Docker image](https://github.com/dockur/windows) for further information.
+
+This compose file uses Windows 11 by default. You can use Windows 10 by changing the `VERSION` to `tiny10`.
+
+> [!NOTE]
+> We use a stripped-down Windows installation by default. This is recommended, but you can still opt for stock windows by changing the version to one of the versions listed in the README of the images repository linked above.
+
+> [!NOTE]
+> Older versions than Windows 10 are not officially supported by us. However they might still work with some additional tuning.
+
+You can now just run:
+```shell
+docker compose up -d
+```
+to run the VM in the background.
+
+After this just open http://127.0.0.1:8006 in your web browser and wait for the Windows installation to finish.
+
+> [!WARNING]
+> Make sure to change the `RDP_IP` in your winapps config to `127.0.0.1`.
+
+Now you should be ready to go and try to connect to your VM with winapps.
+
+For stopping the VM just use:
+```shell
+docker compose stop
+```
+
+For starting again afterwards use:
+```shell
+docker compose start
+```
+
+(All compose commands have to be run from the directory where the `compose.yaml` is located.)
diff --git a/icons/windows.svg b/icons/windows.svg
index aff2730..6296a2a 100644
--- a/icons/windows.svg
+++ b/icons/windows.svg
@@ -1,3 +1,3 @@
-
+
diff --git a/install/ExtractPrograms.ps1 b/install/ExtractPrograms.ps1
index 0111190..eff0a08 100644
--- a/install/ExtractPrograms.ps1
+++ b/install/ExtractPrograms.ps1
@@ -63,7 +63,7 @@ Function Get-Icon {
.EXAMPLE
Get-Icon -Path 'C:\windows\system32\WindowsPowerShell\v1.0\PowerShell.exe' -ToBitmap
- Tag :
+ Tag :
PhysicalDimension : {Width=32, Height=32}
Size : {Width=32, Height=32}
Width : 32
@@ -173,25 +173,25 @@ Function Get-Icon {
$Path = Convert-Path -Path $Path
Write-Debug $Path
If (Test-Path -Path $Path) {
- #$Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($Path)|
- $Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($Path)|
+ #$Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($Path)|
+ $Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($Path)|
Add-Member -MemberType NoteProperty -Name FullName -Value $Path -PassThru
If ($PSBoundParameters.ContainsKey('ToBytes')) {
Write-Verbose "Retrieving bytes"
$MemoryStream = New-Object System.IO.MemoryStream
$Icon.save($MemoryStream)
Write-Debug ($MemoryStream | Out-String)
- $MemoryStream.ToArray()
- $MemoryStream.Flush()
- $MemoryStream.Dispose()
+ $MemoryStream.ToArray()
+ $MemoryStream.Flush()
+ $MemoryStream.Dispose()
} ElseIf ($PSBoundParameters.ContainsKey('ToBitmap')) {
$Icon.ToBitMap()
} ElseIf ($PSBoundParameters.ContainsKey('ToBase64')) {
$MemoryStream = New-Object System.IO.MemoryStream
$Icon.save($MemoryStream)
Write-Debug ($MemoryStream | Out-String)
- $Bytes = $MemoryStream.ToArray()
- $MemoryStream.Flush()
+ $Bytes = $MemoryStream.ToArray()
+ $MemoryStream.Flush()
$MemoryStream.Dispose()
[convert]::ToBase64String($Bytes)
} Else {
@@ -219,4 +219,3 @@ Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\*" |
"EXES+=(""$Exe"")"
"ICONS+=(""$Icon"")"
}
-
diff --git a/install/inquirer.sh b/install/inquirer.sh
index 00194a8..2b9e962 100755
--- a/install/inquirer.sh
+++ b/install/inquirer.sh
@@ -26,6 +26,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
+# shellcheck disable=all
+
# store the current set options
OLD_SET=$-
set -e
@@ -49,785 +51,785 @@ normal="$(tput sgr0)"
dim=$'\e[2m'
print() {
- echo "$1"
- tput el
+ echo "$1"
+ tput el
}
join() {
- local IFS=$'\n'
- local _join_list
- eval _join_list=( '"${'${1}'[@]}"' )
- local first=true
- for item in ${_join_list[@]}; do
- if [ "$first" = true ]; then
- printf "%s" "$item"
- first=false
- else
- printf "${2-, }%s" "$item"
- fi
- done
+ local IFS=$'\n'
+ local _join_list
+ eval _join_list=( '"${'${1}'[@]}"' )
+ local first=true
+ for item in ${_join_list[@]}; do
+ if [ "$first" = true ]; then
+ printf "%s" "$item"
+ first=false
+ else
+ printf "${2-, }%s" "$item"
+ fi
+ done
}
function gen_env_from_options() {
- local IFS=$'\n'
- local _indices
- local _env_names
- local _checkbox_selected
- eval _indices=( '"${'${1}'[@]}"' )
- eval _env_names=( '"${'${2}'[@]}"' )
+ local IFS=$'\n'
+ local _indices
+ local _env_names
+ local _checkbox_selected
+ eval _indices=( '"${'${1}'[@]}"' )
+ eval _env_names=( '"${'${2}'[@]}"' )
- for i in $(gen_index ${#_env_names[@]}); do
- _checkbox_selected[$i]=false
- done
+ for i in $(gen_index ${#_env_names[@]}); do
+ _checkbox_selected[$i]=false
+ done
- for i in ${_indices[@]}; do
- _checkbox_selected[$i]=true
- done
+ for i in ${_indices[@]}; do
+ _checkbox_selected[$i]=true
+ done
- for i in $(gen_index ${#_env_names[@]}); do
- printf "%s=%s\n" "${_env_names[$i]}" "${_checkbox_selected[$i]}"
- done
+ for i in $(gen_index ${#_env_names[@]}); do
+ printf "%s=%s\n" "${_env_names[$i]}" "${_checkbox_selected[$i]}"
+ done
}
on_default() {
- true;
+ true;
}
on_keypress() {
- local OLD_IFS
- local IFS
- local key
- OLD_IFS=$IFS
- local on_up=${1:-on_default}
- local on_down=${2:-on_default}
- local on_space=${3:-on_default}
- local on_enter=${4:-on_default}
- local on_left=${5:-on_default}
- local on_right=${6:-on_default}
- local on_ascii=${7:-on_default}
- local on_backspace=${8:-on_default}
- _break_keypress=false
- while IFS="" read -rsn1 key; do
- case "$key" in
- $'\x1b')
- read -rsn1 key
- if [[ "$key" == "[" ]]; then
- read -rsn1 key
- case "$key" in
- 'A') eval $on_up;;
- 'B') eval $on_down;;
- 'D') eval $on_left;;
- 'C') eval $on_right;;
- esac
- fi
- ;;
- ' ') eval $on_space ' ';;
- [a-z0-9A-Z\!\#\$\&\+\,\-\.\/\;\=\?\@\[\]\^\_\{\}\~]) eval $on_ascii $key;;
- $'\x7f') eval $on_backspace $key;;
- '') eval $on_enter $key;;
- esac
- if [ $_break_keypress = true ]; then
- break
- fi
- done
- IFS=$OLD_IFS
+ local OLD_IFS
+ local IFS
+ local key
+ OLD_IFS=$IFS
+ local on_up=${1:-on_default}
+ local on_down=${2:-on_default}
+ local on_space=${3:-on_default}
+ local on_enter=${4:-on_default}
+ local on_left=${5:-on_default}
+ local on_right=${6:-on_default}
+ local on_ascii=${7:-on_default}
+ local on_backspace=${8:-on_default}
+ _break_keypress=false
+ while IFS="" read -rsn1 key; do
+ case "$key" in
+ $'\x1b')
+ read -rsn1 key
+ if [[ "$key" == "[" ]]; then
+ read -rsn1 key
+ case "$key" in
+ 'A') eval $on_up ;;
+ 'B') eval $on_down ;;
+ 'D') eval $on_left ;;
+ 'C') eval $on_right ;;
+ esac
+ fi
+ ;;
+ ' ') eval $on_space ' ' ;;
+ [a-z0-9A-Z\!\#\$\&\+\,\-\.\/\;\=\?\@\[\]\^\_\{\}\~]) eval $on_ascii $key ;;
+ $'\x7f') eval $on_backspace $key ;;
+ '') eval $on_enter $key ;;
+ esac
+ if [ $_break_keypress = true ]; then
+ break
+ fi
+ done
+ IFS=$OLD_IFS
}
gen_index() {
- local k=$1
- local l=0
- if [ $k -gt 0 ]; then
- for l in $(seq $k)
- do
- echo "$l-1" | bc
- done
- fi
+ local k=$1
+ local l=0
+ if [ $k -gt 0 ]; then
+ for l in $(seq $k)
+ do
+ echo "$l-1" | bc
+ done
+ fi
}
cleanup() {
- # Reset character attributes, make cursor visible, and restore
- # previous screen contents (if possible).
- tput sgr0
- tput cnorm
- stty echo
+ # Reset character attributes, make cursor visible, and restore
+ # previous screen contents (if possible).
+ tput sgr0
+ tput cnorm
+ stty echo
- # Restore `set e` option to its orignal value
- if [[ $OLD_SET =~ e ]]
- then set -e
- else set +e
- fi
+ # Restore `set e` option to its orignal value
+ if [[ $OLD_SET =~ e ]]
+ then set -e
+ else set +e
+ fi
}
control_c() {
- cleanup
- exit $?
+ cleanup
+ exit $?
}
select_indices() {
- local _select_list
- local _select_indices
- local _select_selected=()
- eval _select_list=( '"${'${1}'[@]}"' )
- eval _select_indices=( '"${'${2}'[@]}"' )
- local _select_var_name=$3
- eval $_select_var_name\=\(\)
- for i in $(gen_index ${#_select_indices[@]}); do
- eval $_select_var_name\+\=\(\""${_select_list[${_select_indices[$i]}]}"\"\)
- done
+ local _select_list
+ local _select_indices
+ local _select_selected=()
+ eval _select_list=( '"${'${1}'[@]}"' )
+ eval _select_indices=( '"${'${2}'[@]}"' )
+ local _select_var_name=$3
+ eval $_select_var_name\=\(\)
+ for i in $(gen_index ${#_select_indices[@]}); do
+ eval $_select_var_name\+\=\(\""${_select_list[${_select_indices[$i]}]}"\"\)
+ done
}
print_checkbox_line_arrow() {
- if [ "${_checkbox_selected[$1]}" = true ]; then
- printf "${cyan}${arrow}${green}${checked}${normal} ${_checkbox_list[$1]} ${normal}"
- else
- printf "${cyan}${arrow}${normal}${unchecked} ${_checkbox_list[$1]} ${normal}"
- fi
+ if [ "${_checkbox_selected[$1]}" = true ]; then
+ printf "${cyan}${arrow}${green}${checked}${normal} ${_checkbox_list[$1]} ${normal}"
+ else
+ printf "${cyan}${arrow}${normal}${unchecked} ${_checkbox_list[$1]} ${normal}"
+ fi
}
print_checkbox_line() {
- if [ "${_checkbox_selected[$1]}" = true ]; then
- printf " ${green}${checked}${normal} ${_checkbox_list[$1]} ${normal}"
- else
- printf " ${normal}${unchecked} ${_checkbox_list[$1]} ${normal}"
- fi
+ if [ "${_checkbox_selected[$1]}" = true ]; then
+ printf " ${green}${checked}${normal} ${_checkbox_list[$1]} ${normal}"
+ else
+ printf " ${normal}${unchecked} ${_checkbox_list[$1]} ${normal}"
+ fi
}
# https://www.gnu.org/software/termutils/manual/termutils-2.0/html_chapter/tput_1.html
# http://linuxcommand.org/lc3_adv_tput.php
on_checkbox_input_up2() {
- #remove_checkbox_instructions
- tput cub "$(tput cols)"
-
- if [ "${_checkbox_selected[$_current_index]}" = true ]; then
- printf " ${green}${checked}${normal} ${_checkbox_list[$_current_index]} ${normal}"
- else
- printf " ${unchecked} ${_checkbox_list[$_current_index]} ${normal}"
- fi
- tput el
-
- if [ $_current_index = 0 ]; then
- _current_index=$((${#_checkbox_list[@]}-1))
- tput cud $((${#_checkbox_list[@]}-1))
+ #remove_checkbox_instructions
tput cub "$(tput cols)"
- else
- _current_index=$((_current_index-1))
- tput cuu1 # Up one line
- tput cub "$(tput cols)" # Back to beginning (does this work?)
- tput el # Clear to end of line
- fi
+ if [ "${_checkbox_selected[$_current_index]}" = true ]; then
+ printf " ${green}${checked}${normal} ${_checkbox_list[$_current_index]} ${normal}"
+ else
+ printf " ${unchecked} ${_checkbox_list[$_current_index]} ${normal}"
+ fi
+ tput el
- if [ "${_checkbox_selected[$_current_index]}" = true ]; then
- printf "${cyan}${arrow}${green}${checked}${normal} ${_checkbox_list[$_current_index]} ${normal}"
- else
- printf "${cyan}${arrow}${normal}${unchecked} ${_checkbox_list[$_current_index]} ${normal}"
- fi
+ if [ $_current_index = 0 ]; then
+ _current_index=$((${#_checkbox_list[@]}-1))
+ tput cud $((${#_checkbox_list[@]}-1))
+ tput cub "$(tput cols)"
+ else
+ _current_index=$((_current_index-1))
+
+ tput cuu1 # Up one line
+ tput cub "$(tput cols)" # Back to beginning (does this work?)
+ tput el # Clear to end of line
+ fi
+
+ if [ "${_checkbox_selected[$_current_index]}" = true ]; then
+ printf "${cyan}${arrow}${green}${checked}${normal} ${_checkbox_list[$_current_index]} ${normal}"
+ else
+ printf "${cyan}${arrow}${normal}${unchecked} ${_checkbox_list[$_current_index]} ${normal}"
+ fi
}
on_checkbox_input_up() {
- #remove_checkbox_instructions
- tput cub "$(tput cols)"
- if (( ${_current_row} > 0 )) || (( ${#_checkbox_list[@]} <= 5 )); then
- print_checkbox_line $_current_index
- tput el
- if [ $_current_index = 0 ]; then
- _current_index=$((${#_checkbox_list[@]}-1))
- _current_row=4
- tput cud $((${#_checkbox_list[@]}-1))
- tput cub "$(tput cols)"
+ #remove_checkbox_instructions
+ tput cub "$(tput cols)"
+ if (( ${_current_row} > 0 )) || (( ${#_checkbox_list[@]} <= 5 )); then
+ print_checkbox_line $_current_index
+ tput el
+ if [ $_current_index = 0 ]; then
+ _current_index=$((${#_checkbox_list[@]}-1))
+ _current_row=4
+ tput cud $((${#_checkbox_list[@]}-1))
+ tput cub "$(tput cols)"
+ else
+ _current_index=$((_current_index-1))
+ _current_row=$((_current_row-1))
+ tput cuu1
+ tput cub "$(tput cols)"
+ tput el
+ fi
+ print_checkbox_line_arrow $_current_index
else
- _current_index=$((_current_index-1))
- _current_row=$((_current_row-1))
- tput cuu1
- tput cub "$(tput cols)"
- tput el
+ if [ $_current_index = 0 ]; then
+ _current_index=$((${#_checkbox_list[@]}-1))
+ _current_row=4
+ tput cuu 1
+ tput cub "$(tput cols)"
+ tput el
+ printf " ${cyan}${up_arrow}${normal}"
+ for I in 4 3 2 1; do
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ print_checkbox_line $((_current_index-I))
+ done
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ print_checkbox_line_arrow $((_current_index))
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ printf " ${dim}${down_arrow}${normal}"
+ tput cuu 1
+ else
+ _current_index=$((_current_index-1))
+ tput cud 5
+ tput cub "$(tput cols)"
+ tput el
+ printf " ${cyan}${down_arrow}${normal}"
+ for I in 4 3 2 1; do
+ tput cuu1
+ tput cub "$(tput cols)"
+ tput el
+ print_checkbox_line $((_current_index+I))
+ done
+ tput cuu1
+ tput cub "$(tput cols)"
+ tput el
+ print_checkbox_line_arrow $((_current_index))
+ if [ $_current_index = 0 ]; then
+ tput cuu1
+ tput cub "$(tput cols)"
+ tput el
+ printf " ${dim}${up_arrow}${normal}"
+ tput cud1
+ fi
+ fi
fi
- print_checkbox_line_arrow $_current_index
- else
- if [ $_current_index = 0 ]; then
- _current_index=$((${#_checkbox_list[@]}-1))
- _current_row=4
- tput cuu 1
- tput cub "$(tput cols)"
- tput el
- printf " ${cyan}${up_arrow}${normal}"
- for I in 4 3 2 1; do
- tput cud1
- tput cub "$(tput cols)"
- tput el
- print_checkbox_line $((_current_index-I))
- done
- tput cud1
- tput cub "$(tput cols)"
- tput el
- print_checkbox_line_arrow $((_current_index))
- tput cud1
- tput cub "$(tput cols)"
- tput el
- printf " ${dim}${down_arrow}${normal}"
- tput cuu 1
- else
- _current_index=$((_current_index-1))
- tput cud 5
- tput cub "$(tput cols)"
- tput el
- printf " ${cyan}${down_arrow}${normal}"
- for I in 4 3 2 1; do
- tput cuu1
- tput cub "$(tput cols)"
- tput el
- print_checkbox_line $((_current_index+I))
- done
- tput cuu1
- tput cub "$(tput cols)"
- tput el
- print_checkbox_line_arrow $((_current_index))
- if [ $_current_index = 0 ]; then
- tput cuu1
- tput cub "$(tput cols)"
- tput el
- printf " ${dim}${up_arrow}${normal}"
- tput cud1
- fi
- fi
- fi
}
on_checkbox_input_down() {
- #remove_checkbox_instructions
- tput cub "$(tput cols)"
- if (( ${_current_row} < 4 )) || (( ${#_checkbox_list[@]} <= 5 )); then
- print_checkbox_line $_current_index
- tput el
- if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then
- _current_index=0
- _current_row=0
- tput cuu $((${#_checkbox_list[@]}-1))
- tput cub "$(tput cols)"
+ #remove_checkbox_instructions
+ tput cub "$(tput cols)"
+ if (( ${_current_row} < 4 )) || (( ${#_checkbox_list[@]} <= 5 )); then
+ print_checkbox_line $_current_index
+ tput el
+ if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then
+ _current_index=0
+ _current_row=0
+ tput cuu $((${#_checkbox_list[@]}-1))
+ tput cub "$(tput cols)"
+ else
+ _current_index=$((_current_index+1))
+ _current_row=$((_current_row+1))
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ fi
+ print_checkbox_line_arrow $_current_index
else
- _current_index=$((_current_index+1))
- _current_row=$((_current_row+1))
- tput cud1
- tput cub "$(tput cols)"
- tput el
+ if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then
+ _current_index=0
+ _current_row=0
+ tput cuu 5
+ tput cub "$(tput cols)"
+ tput el
+ printf " ${dim}${up_arrow}${normal}"
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ print_checkbox_line_arrow $((_current_index))
+ for I in 1 2 3 4; do
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ print_checkbox_line $((_current_index+I))
+ done
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ printf " ${cyan}${down_arrow}${normal}"
+ tput cuu 5
+ else
+ _current_index=$((_current_index+1))
+ tput cuu 5
+ tput cub "$(tput cols)"
+ tput el
+ printf " ${cyan}${up_arrow}${normal}"
+ for I in 4 3 2 1; do
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ print_checkbox_line $((_current_index-I))
+ done
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ print_checkbox_line_arrow $((_current_index))
+ if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ printf " ${dim}${down_arrow}${normal}"
+ tput cuu1
+ fi
+ fi
fi
- print_checkbox_line_arrow $_current_index
- else
- if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then
- _current_index=0
- _current_row=0
- tput cuu 5
- tput cub "$(tput cols)"
- tput el
- printf " ${dim}${up_arrow}${normal}"
- tput cud1
- tput cub "$(tput cols)"
- tput el
- print_checkbox_line_arrow $((_current_index))
- for I in 1 2 3 4; do
- tput cud1
- tput cub "$(tput cols)"
- tput el
- print_checkbox_line $((_current_index+I))
- done
- tput cud1
- tput cub "$(tput cols)"
- tput el
- printf " ${cyan}${down_arrow}${normal}"
- tput cuu 5
- else
- _current_index=$((_current_index+1))
- tput cuu 5
- tput cub "$(tput cols)"
- tput el
- printf " ${cyan}${up_arrow}${normal}"
- for I in 4 3 2 1; do
- tput cud1
- tput cub "$(tput cols)"
- tput el
- print_checkbox_line $((_current_index-I))
- done
- tput cud1
- tput cub "$(tput cols)"
- tput el
- print_checkbox_line_arrow $((_current_index))
- if [ $_current_index = $((${#_checkbox_list[@]}-1)) ]; then
- tput cud1
- tput cub "$(tput cols)"
- tput el
- printf " ${dim}${down_arrow}${normal}"
- tput cuu1
- fi
- fi
- fi
}
on_checkbox_input_enter() {
- remove_checkbox_instructions
- local OLD_IFS
- OLD_IFS=$IFS
- _checkbox_selected_indices=()
- _checkbox_selected_options=()
- IFS=$'\n'
+ remove_checkbox_instructions
+ local OLD_IFS
+ OLD_IFS=$IFS
+ _checkbox_selected_indices=()
+ _checkbox_selected_options=()
+ IFS=$'\n'
- for i in $(gen_index ${#_checkbox_list[@]}); do
- if [ "${_checkbox_selected[$i]}" = true ]; then
- _checkbox_selected_indices+=($i)
- _checkbox_selected_options+=("${_checkbox_list[$i]}")
+ for i in $(gen_index ${#_checkbox_list[@]}); do
+ if [ "${_checkbox_selected[$i]}" = true ]; then
+ _checkbox_selected_indices+=($i)
+ _checkbox_selected_options+=("${_checkbox_list[$i]}")
+ fi
+ done
+
+ if (( ${#_checkbox_list[@]} <= 5 )); then
+ tput cud $((${#_checkbox_list[@]}-${_current_index}))
+ tput cub "$(tput cols)"
+ for i in $(seq $((${#_checkbox_list[@]}+1))); do
+ tput el1
+ tput el
+ tput cuu1
+ done
+ else
+ tput cud $((6-${_current_row}))
+ tput cub "$(tput cols)"
+ for i in $(seq 8); do
+ tput el1
+ tput el
+ tput cuu1
+ done
fi
- done
-
- if (( ${#_checkbox_list[@]} <= 5 )); then
- tput cud $((${#_checkbox_list[@]}-${_current_index}))
tput cub "$(tput cols)"
- for i in $(seq $((${#_checkbox_list[@]}+1))); do
- tput el1
- tput el
- tput cuu1
- done
- else
- tput cud $((6-${_current_row}))
+
+ tput cuf $((${#prompt}+3))
+ printf "${cyan}$(join _checkbox_selected_options)${normal}"
+ tput el
+
+ tput cud1
tput cub "$(tput cols)"
- for i in $(seq 8); do
- tput el1
- tput el
- tput cuu1
- done
- fi
- tput cub "$(tput cols)"
+ tput el
- tput cuf $((${#prompt}+3))
- printf "${cyan}$(join _checkbox_selected_options)${normal}"
- tput el
-
- tput cud1
- tput cub "$(tput cols)"
- tput el
-
- _break_keypress=true
- IFS=$OLD_IFS
+ _break_keypress=true
+ IFS=$OLD_IFS
}
on_checkbox_input_space() {
- #remove_checkbox_instructions
- tput cub "$(tput cols)"
- tput el
- if [ "${_checkbox_selected[$_current_index]}" = true ]; then
- _checkbox_selected[$_current_index]=false
- else
- _checkbox_selected[$_current_index]=true
- fi
+ #remove_checkbox_instructions
+ tput cub "$(tput cols)"
+ tput el
+ if [ "${_checkbox_selected[$_current_index]}" = true ]; then
+ _checkbox_selected[$_current_index]=false
+ else
+ _checkbox_selected[$_current_index]=true
+ fi
- print_checkbox_line_arrow $_current_index
+ print_checkbox_line_arrow $_current_index
}
remove_checkbox_instructions() {
- if [ $_first_keystroke = true ]; then
- tput cuu $((${_current_index}+1))
- tput cub "$(tput cols)"
- tput cuf $((${#prompt}+3))
- tput el
- tput cud $((${_current_index}+1))
- _first_keystroke=false
- fi
+ if [ $_first_keystroke = true ]; then
+ tput cuu $((${_current_index}+1))
+ tput cub "$(tput cols)"
+ tput cuf $((${#prompt}+3))
+ tput el
+ tput cud $((${_current_index}+1))
+ _first_keystroke=false
+ fi
}
# for vim movements
on_checkbox_input_ascii() {
- local key=$1
- case $key in
- "j" ) on_checkbox_input_down;;
- "k" ) on_checkbox_input_up;;
- esac
+ local key=$1
+ case $key in
+ "j" ) on_checkbox_input_down ;;
+ "k" ) on_checkbox_input_up ;;
+ esac
}
_checkbox_input() {
- local i
- local j
- prompt=$1
- eval _checkbox_list=( '"${'${2}'[@]}"' )
- _current_index=0
- _current_row=0
- _first_keystroke=true
+ local i
+ local j
+ prompt=$1
+ eval _checkbox_list=( '"${'${2}'[@]}"' )
+ _current_index=0
+ _current_row=0
+ _first_keystroke=true
- trap control_c SIGINT EXIT
+ trap control_c SIGINT EXIT
- stty -echo
- tput civis
+ stty -echo
+ tput civis
- print "${normal}${green}?${normal} ${bold}${prompt}${normal} ${dim}(Press to select, to finalize)${normal}"
+ print "${normal}${green}?${normal} ${bold}${prompt}${normal} ${dim}(Press to select, to finalize)${normal}"
- for i in $(gen_index ${#_checkbox_list[@]}); do
- _checkbox_selected[$i]=false
- done
-
- if [ -n "$3" ]; then
- eval _selected_indices=( '"${'${3}'[@]}"' )
- for i in ${_selected_indices[@]}; do
- _checkbox_selected[$i]=true
+ for i in $(gen_index ${#_checkbox_list[@]}); do
+ _checkbox_selected[$i]=false
done
- fi
- if (( ${#_checkbox_list[@]} > 5 )); then
- tput cub "$(tput cols)"
- print " ${dim}${up_arrow}${normal}"
- fi
-
- for i in $(gen_index ${#_checkbox_list[@]}); do
- tput cub "$(tput cols)"
- if [ $i = 0 ]; then
- print_checkbox_line_arrow $i
- else
- print_checkbox_line $i
+ if [ -n "$3" ]; then
+ eval _selected_indices=( '"${'${3}'[@]}"' )
+ for i in ${_selected_indices[@]}; do
+ _checkbox_selected[$i]=true
+ done
fi
- print ""
- tput el
- if (( $i > 3 )) && (( ${#_checkbox_list[@]} > 5 )); then
- print " ${cyan}${down_arrow}${normal}"
- break
- fi
- done
- for j in $(gen_index ${#_checkbox_list[@]}); do
- tput cuu1
- if (( $j > 4 )); then
- break
+ if (( ${#_checkbox_list[@]} > 5 )); then
+ tput cub "$(tput cols)"
+ print " ${dim}${up_arrow}${normal}"
fi
- done
- on_keypress on_checkbox_input_up on_checkbox_input_down on_checkbox_input_space on_checkbox_input_enter on_default on_default on_checkbox_input_ascii
+ for i in $(gen_index ${#_checkbox_list[@]}); do
+ tput cub "$(tput cols)"
+ if [ $i = 0 ]; then
+ print_checkbox_line_arrow $i
+ else
+ print_checkbox_line $i
+ fi
+ print ""
+ tput el
+ if (( $i > 3 )) && (( ${#_checkbox_list[@]} > 5 )); then
+ print " ${cyan}${down_arrow}${normal}"
+ break
+ fi
+ done
+
+ for j in $(gen_index ${#_checkbox_list[@]}); do
+ tput cuu1
+ if (( $j > 4 )); then
+ break
+ fi
+ done
+
+ on_keypress on_checkbox_input_up on_checkbox_input_down on_checkbox_input_space on_checkbox_input_enter on_default on_default on_checkbox_input_ascii
}
checkbox_input() {
- _checkbox_input "$1" "$2"
- _checkbox_input_output_var_name=$3
- select_indices _checkbox_list _checkbox_selected_indices $_checkbox_input_output_var_name
+ _checkbox_input "$1" "$2"
+ _checkbox_input_output_var_name=$3
+ select_indices _checkbox_list _checkbox_selected_indices $_checkbox_input_output_var_name
- unset _checkbox_list
- unset _break_keypress
- unset _first_keystroke
- unset _current_index
- unset _checkbox_input_output_var_name
- unset _checkbox_selected_indices
- unset _checkbox_selected_options
+ unset _checkbox_list
+ unset _break_keypress
+ unset _first_keystroke
+ unset _current_index
+ unset _checkbox_input_output_var_name
+ unset _checkbox_selected_indices
+ unset _checkbox_selected_options
- cleanup
+ cleanup
}
checkbox_input_indices() {
- _checkbox_input "$1" "$2" "$3"
- _checkbox_input_output_var_name=$3
+ _checkbox_input "$1" "$2" "$3"
+ _checkbox_input_output_var_name=$3
- eval $_checkbox_input_output_var_name\=\(\)
- for i in $(gen_index ${#_checkbox_selected_indices[@]}); do
- eval $_checkbox_input_output_var_name\+\=\(${_checkbox_selected_indices[$i]}\)
- done
+ eval $_checkbox_input_output_var_name\=\(\)
+ for i in $(gen_index ${#_checkbox_selected_indices[@]}); do
+ eval $_checkbox_input_output_var_name\+\=\(${_checkbox_selected_indices[$i]}\)
+ done
- unset _checkbox_list
- unset _break_keypress
- unset _first_keystroke
- unset _current_index
- unset _checkbox_input_output_var_name
- unset _checkbox_selected_indices
- unset _checkbox_selected_options
+ unset _checkbox_list
+ unset _break_keypress
+ unset _first_keystroke
+ unset _current_index
+ unset _checkbox_input_output_var_name
+ unset _checkbox_selected_indices
+ unset _checkbox_selected_options
- cleanup
+ cleanup
}
on_list_input_up() {
- remove_list_instructions
- tput cub "$(tput cols)"
-
- printf " ${_list_options[$_list_selected_index]}"
- tput el
-
- if [ $_list_selected_index = 0 ]; then
- _list_selected_index=$((${#_list_options[@]}-1))
- tput cud $((${#_list_options[@]}-1))
+ remove_list_instructions
tput cub "$(tput cols)"
- else
- _list_selected_index=$((_list_selected_index-1))
- tput cuu1
- tput cub "$(tput cols)"
+ printf " ${_list_options[$_list_selected_index]}"
tput el
- fi
- printf "${cyan}${arrow} %s ${normal}" "${_list_options[$_list_selected_index]}"
+ if [ $_list_selected_index = 0 ]; then
+ _list_selected_index=$((${#_list_options[@]}-1))
+ tput cud $((${#_list_options[@]}-1))
+ tput cub "$(tput cols)"
+ else
+ _list_selected_index=$((_list_selected_index-1))
+
+ tput cuu1
+ tput cub "$(tput cols)"
+ tput el
+ fi
+
+ printf "${cyan}${arrow} %s ${normal}" "${_list_options[$_list_selected_index]}"
}
on_list_input_down() {
- remove_list_instructions
- tput cub "$(tput cols)"
-
- printf " ${_list_options[$_list_selected_index]}"
- tput el
-
- if [ $_list_selected_index = $((${#_list_options[@]}-1)) ]; then
- _list_selected_index=0
- tput cuu $((${#_list_options[@]}-1))
- tput cub "$(tput cols)"
- else
- _list_selected_index=$((_list_selected_index+1))
- tput cud1
+ remove_list_instructions
tput cub "$(tput cols)"
+
+ printf " ${_list_options[$_list_selected_index]}"
tput el
- fi
- printf "${cyan}${arrow} %s ${normal}" "${_list_options[$_list_selected_index]}"
+
+ if [ $_list_selected_index = $((${#_list_options[@]}-1)) ]; then
+ _list_selected_index=0
+ tput cuu $((${#_list_options[@]}-1))
+ tput cub "$(tput cols)"
+ else
+ _list_selected_index=$((_list_selected_index+1))
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ fi
+ printf "${cyan}${arrow} %s ${normal}" "${_list_options[$_list_selected_index]}"
}
on_list_input_enter_space() {
- local OLD_IFS
- OLD_IFS=$IFS
- IFS=$'\n'
+ local OLD_IFS
+ OLD_IFS=$IFS
+ IFS=$'\n'
- tput cud $((${#_list_options[@]}-${_list_selected_index}))
- tput cub "$(tput cols)"
+ tput cud $((${#_list_options[@]}-${_list_selected_index}))
+ tput cub "$(tput cols)"
- for i in $(seq $((${#_list_options[@]}+1))); do
- tput el1
+ for i in $(seq $((${#_list_options[@]}+1))); do
+ tput el1
+ tput el
+ tput cuu1
+ done
+ tput cub "$(tput cols)"
+
+ tput cuf $((${#prompt}+3))
+ printf "${cyan}${_list_options[$_list_selected_index]}${normal}"
tput el
- tput cuu1
- done
- tput cub "$(tput cols)"
- tput cuf $((${#prompt}+3))
- printf "${cyan}${_list_options[$_list_selected_index]}${normal}"
- tput el
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
- tput cud1
- tput cub "$(tput cols)"
- tput el
-
- _break_keypress=true
- IFS=$OLD_IFS
+ _break_keypress=true
+ IFS=$OLD_IFS
}
remove_list_instructions() {
- if [ $_first_keystroke = true ]; then
- tput cuu $((${_list_selected_index}+1))
- tput cub "$(tput cols)"
- tput cuf $((${#prompt}+3))
- tput el
- tput cud $((${_list_selected_index}+1))
- _first_keystroke=false
- fi
+ if [ $_first_keystroke = true ]; then
+ tput cuu $((${_list_selected_index}+1))
+ tput cub "$(tput cols)"
+ tput cuf $((${#prompt}+3))
+ tput el
+ tput cud $((${_list_selected_index}+1))
+ _first_keystroke=false
+ fi
}
_list_input() {
- local i
- local j
- prompt=$1
- eval _list_options=( '"${'${2}'[@]}"' )
+ local i
+ local j
+ prompt=$1
+ eval _list_options=( '"${'${2}'[@]}"' )
- _list_selected_index=0
- _first_keystroke=true
+ _list_selected_index=0
+ _first_keystroke=true
- trap control_c SIGINT EXIT
+ trap control_c SIGINT EXIT
- stty -echo
- tput civis
+ stty -echo
+ tput civis
- print "${normal}${green}?${normal} ${bold}${prompt}${normal} ${dim}(Use arrow keys)${normal}"
+ print "${normal}${green}?${normal} ${bold}${prompt}${normal} ${dim}(Use arrow keys)${normal}"
- for i in $(gen_index ${#_list_options[@]}); do
- tput cub "$(tput cols)"
- if [ $i = 0 ]; then
- print "${cyan}${arrow} ${_list_options[$i]} ${normal}"
- else
- print " ${_list_options[$i]}"
- fi
- tput el
- done
+ for i in $(gen_index ${#_list_options[@]}); do
+ tput cub "$(tput cols)"
+ if [ $i = 0 ]; then
+ print "${cyan}${arrow} ${_list_options[$i]} ${normal}"
+ else
+ print " ${_list_options[$i]}"
+ fi
+ tput el
+ done
- for j in $(gen_index ${#_list_options[@]}); do
- tput cuu1
- done
+ for j in $(gen_index ${#_list_options[@]}); do
+ tput cuu1
+ done
- on_keypress on_list_input_up on_list_input_down on_list_input_enter_space on_list_input_enter_space
+ on_keypress on_list_input_up on_list_input_down on_list_input_enter_space on_list_input_enter_space
}
list_input() {
- _list_input "$1" "$2"
- local var_name=$3
- eval $var_name=\'"${_list_options[$_list_selected_index]}"\'
- unset _list_selected_index
- unset _list_options
- unset _break_keypress
- unset _first_keystroke
+ _list_input "$1" "$2"
+ local var_name=$3
+ eval $var_name=\'"${_list_options[$_list_selected_index]}"\'
+ unset _list_selected_index
+ unset _list_options
+ unset _break_keypress
+ unset _first_keystroke
- cleanup
+ cleanup
}
list_input_index() {
- _list_input "$1" "$2"
- local var_name=$3
- eval $var_name=\'"$_list_selected_index"\'
- unset _list_selected_index
- unset _list_options
- unset _break_keypress
- unset _first_keystroke
+ _list_input "$1" "$2"
+ local var_name=$3
+ eval $var_name=\'"$_list_selected_index"\'
+ unset _list_selected_index
+ unset _list_options
+ unset _break_keypress
+ unset _first_keystroke
- cleanup
+ cleanup
}
on_text_input_left() {
- remove_regex_failed
- if [ $_current_pos -gt 0 ]; then
- tput cub1
- _current_pos=$(($_current_pos-1))
- fi
+ remove_regex_failed
+ if [ $_current_pos -gt 0 ]; then
+ tput cub1
+ _current_pos=$(($_current_pos-1))
+ fi
}
on_text_input_right() {
- remove_regex_failed
- if [ $_current_pos -lt ${#_text_input} ]; then
- tput cuf1
- _current_pos=$(($_current_pos+1))
- fi
+ remove_regex_failed
+ if [ $_current_pos -lt ${#_text_input} ]; then
+ tput cuf1
+ _current_pos=$(($_current_pos+1))
+ fi
}
on_text_input_enter() {
- remove_regex_failed
+ remove_regex_failed
- if [[ "$_text_input" =~ $_text_input_regex && "$(eval $_text_input_validator "$_text_input")" = true ]]; then
- tput cub "$(tput cols)"
- tput cuf $((${#_read_prompt}-19))
- printf "${cyan}${_text_input}${normal}"
- tput el
- tput cud1
- tput cub "$(tput cols)"
- tput el
- eval $var_name=\'"${_text_input}"\'
- _break_keypress=true
- else
- _text_input_regex_failed=true
- tput civis
- tput cud1
- tput cub "$(tput cols)"
- tput el
- printf "${red}>>${normal} $_text_input_regex_failed_msg"
- tput cuu1
- tput cub "$(tput cols)"
- tput cuf $((${#_read_prompt}-19))
- tput el
- _text_input=""
- _current_pos=0
- tput cnorm
- fi
+ if [[ "$_text_input" =~ $_text_input_regex && "$(eval $_text_input_validator "$_text_input")" = true ]]; then
+ tput cub "$(tput cols)"
+ tput cuf $((${#_read_prompt}-19))
+ printf "${cyan}${_text_input}${normal}"
+ tput el
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ eval $var_name=\'"${_text_input}"\'
+ _break_keypress=true
+ else
+ _text_input_regex_failed=true
+ tput civis
+ tput cud1
+ tput cub "$(tput cols)"
+ tput el
+ printf "${red}>>${normal} $_text_input_regex_failed_msg"
+ tput cuu1
+ tput cub "$(tput cols)"
+ tput cuf $((${#_read_prompt}-19))
+ tput el
+ _text_input=""
+ _current_pos=0
+ tput cnorm
+ fi
}
on_text_input_ascii() {
- remove_regex_failed
- local c=$1
+ remove_regex_failed
+ local c=$1
- if [ "$c" = '' ]; then
- c=' '
- fi
+ if [ "$c" = '' ]; then
+ c=' '
+ fi
- local rest="${_text_input:$_current_pos}"
- _text_input="${_text_input:0:$_current_pos}$c$rest"
- _current_pos=$(($_current_pos+1))
+ local rest="${_text_input:$_current_pos}"
+ _text_input="${_text_input:0:$_current_pos}$c$rest"
+ _current_pos=$(($_current_pos+1))
- tput civis
- printf "$c$rest"
- tput el
- if [ ${#rest} -gt 0 ]; then
- tput cub ${#rest}
- fi
- tput cnorm
+ tput civis
+ printf "$c$rest"
+ tput el
+ if [ ${#rest} -gt 0 ]; then
+ tput cub ${#rest}
+ fi
+ tput cnorm
}
on_text_input_backspace() {
- remove_regex_failed
- if [ $_current_pos -gt 0 ]; then
- local start="${_text_input:0:$(($_current_pos-1))}"
- local rest="${_text_input:$_current_pos}"
- _current_pos=$(($_current_pos-1))
- tput cub 1
- tput el
- tput sc
- printf "$rest"
- tput rc
- _text_input="$start$rest"
- fi
+ remove_regex_failed
+ if [ $_current_pos -gt 0 ]; then
+ local start="${_text_input:0:$(($_current_pos-1))}"
+ local rest="${_text_input:$_current_pos}"
+ _current_pos=$(($_current_pos-1))
+ tput cub 1
+ tput el
+ tput sc
+ printf "$rest"
+ tput rc
+ _text_input="$start$rest"
+ fi
}
remove_regex_failed() {
- if [ $_text_input_regex_failed = true ]; then
- _text_input_regex_failed=false
- tput sc
- tput cud1
- tput el1
- tput el
- tput rc
- fi
+ if [ $_text_input_regex_failed = true ]; then
+ _text_input_regex_failed=false
+ tput sc
+ tput cud1
+ tput el1
+ tput el
+ tput rc
+ fi
}
text_input_default_validator() {
- echo true;
+ echo true;
}
text_input() {
- local prompt=$1
- local var_name=$2
- local _text_input_regex="${3:-"\.+"}"
- local _text_input_regex_failed_msg=${4:-"Input validation failed"}
- local _text_input_validator=${5:-text_input_default_validator}
- local _read_prompt_start=$'\e[32m?\e[39m\e[1m'
- local _read_prompt_end=$'\e[22m'
- local _read_prompt="$( echo "$_read_prompt_start ${prompt} $_read_prompt_end")"
- local _current_pos=0
- local _text_input_regex_failed=false
- local _text_input=""
- printf "$_read_prompt"
+ local prompt=$1
+ local var_name=$2
+ local _text_input_regex="${3:-"\.+"}"
+ local _text_input_regex_failed_msg=${4:-"Input validation failed"}
+ local _text_input_validator=${5:-text_input_default_validator}
+ local _read_prompt_start=$'\e[32m?\e[39m\e[1m'
+ local _read_prompt_end=$'\e[22m'
+ local _read_prompt="$( echo "$_read_prompt_start ${prompt} $_read_prompt_end")"
+ local _current_pos=0
+ local _text_input_regex_failed=false
+ local _text_input=""
+ printf "$_read_prompt"
- trap control_c SIGINT EXIT
+ trap control_c SIGINT EXIT
- stty -echo
- tput cnorm
+ stty -echo
+ tput cnorm
- on_keypress on_default on_default on_text_input_ascii on_text_input_enter on_text_input_left on_text_input_right on_text_input_ascii on_text_input_backspace
- eval $var_name=\'"${_text_input}"\'
+ on_keypress on_default on_default on_text_input_ascii on_text_input_enter on_text_input_left on_text_input_right on_text_input_ascii on_text_input_backspace
+ eval $var_name=\'"${_text_input}"\'
- cleanup
+ cleanup
}
# =============================================================
function menuFromCmd() {
- local mLOCALRESULT=$1
- local mRESULT=''
- read -r -a ARRAY <<< $3
- list_input "$2" ARRAY mRESULT
- eval $mLOCALRESULT="'$mRESULT'"
+ local mLOCALRESULT=$1
+ local mRESULT=''
+ read -r -a ARRAY <<< $3
+ list_input "$2" ARRAY mRESULT
+ eval $mLOCALRESULT="'$mRESULT'"
}
function menuFromArr() {
- local mLOCALRESULT=$1
- shift
- local PROMPT=$1
- shift
- local ARRAY=("$@")
- list_input "$PROMPT" ARRAY mRESULT
- eval $mLOCALRESULT="'$mRESULT'"
+ local mLOCALRESULT=$1
+ shift
+ local PROMPT=$1
+ shift
+ local ARRAY=("$@")
+ list_input "$PROMPT" ARRAY mRESULT
+ eval $mLOCALRESULT="'$mRESULT'"
}
function multiFromArr() {
- local mLOCALRESULT=$1
- shift
- local PROMPT=$1
- shift
- local ARRAY=("$@")
- checkbox_input "$PROMPT" ARRAY mRESULT
- eval $mLOCALRESULT="'$mRESULT'"
+ local mLOCALRESULT=$1
+ shift
+ local PROMPT=$1
+ shift
+ local ARRAY=("$@")
+ checkbox_input "$PROMPT" ARRAY mRESULT
+ eval $mLOCALRESULT="'$mRESULT'"
}
diff --git a/installer.sh b/installer.sh
index 66fad71..845a435 100755
--- a/installer.sh
+++ b/installer.sh
@@ -1,9 +1,9 @@
#!/usr/bin/env bash
-if ! command -v bc &> /dev/null
+if ! command -v bc &> /dev/null
then
- echo "You need bc!"
- exit
+ echo "You need bc!"
+ exit
fi
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
@@ -11,211 +11,221 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
MAKEDEMO=0
USEDEMO=0
-. "${DIR}/install/inquirer.sh"
+# shellcheck disable=SC1094
+. "$DIR/install/inquirer.sh"
INSTALLED_EXES=()
function waUsage() {
- echo 'Usage:
- ./installer.sh --user # Install everything in ${HOME}
- ./installer.sh --system # Install everything in /usr'
- exit
+ echo "Usage:
+ ./installer.sh --user # Install everything in $HOME
+ ./installer.sh --system # Install everything in /usr"
+ exit
}
function waNoSudo() {
- echo 'You are attempting to switch from a --system install to a --user install.
-Please run "./installer.sh --system --uninstall" first.'
- exit
+ echo "You are attempting to switch from a --system install to a --user install.
+ Please run \"./installer.sh --system --uninstall\" first."
+ exit
}
function waInstall() {
- ${SUDO} mkdir -p "${SYS_PATH}/apps"
- . "${DIR}/bin/winapps" install
+ $SUDO mkdir -p "$SYS_PATH/apps"
+ . "$DIR/bin/winapps" install
}
function waFindInstalled() {
- echo -n " Checking for installed apps in RDP machine (this may take a while)..."
- if [ $USEDEMO != 1 ]; then
- rm -f ${HOME}/.local/share/winapps/installed.bat
- rm -f ${HOME}/.local/share/winapps/installed.tmp
- rm -f ${HOME}/.local/share/winapps/installed
- rm -f ${HOME}/.local/share/winapps/detected
- cp "${DIR}/install/ExtractPrograms.ps1" ${HOME}/.local/share/winapps/ExtractPrograms.ps1
- for F in $(ls "${DIR}/apps"); do
- . "${DIR}/apps/${F}/info"
- echo "IF EXIST \"${WIN_EXECUTABLE}\" ECHO ${F} >> \\\\tsclient\\home\\.local\\share\\winapps\\installed.tmp" >>${HOME}/.local/share/winapps/installed.bat
- done
- echo "powershell.exe -ExecutionPolicy Bypass -File \\\\tsclient\\home\\.local\\share\\winapps\\ExtractPrograms.ps1 > \\\\tsclient\home\\.local\\share\\winapps\\detected" >>${HOME}/.local/share/winapps/installed.bat
- echo "RENAME \\\\tsclient\\home\\.local\\share\\winapps\\installed.tmp installed" >>${HOME}/.local/share/winapps/installed.bat
- $FREERDP_COMMAND /d:"${RDP_DOMAIN}" /u:"${RDP_USER}" /p:"${RDP_PASS}" +auto-reconnect +home-drive -wallpaper +span /app:program:"C:\Windows\System32\cmd.exe",cmd:"/C \\\\tsclient\\home\\.local\\share\\winapps\\installed.bat" /v:${RDP_IP} 1>/dev/null 2>&1 &
- COUNT=0
- while [ ! -f "${HOME}/.local/share/winapps/installed" ]; do
- sleep 5
- COUNT=$((COUNT + 1))
- if ((COUNT == 15)); then
- echo " Finished."
- echo ""
- echo "The RDP connection failed to connect or run. Please confirm FreeRDP can connect with:"
- echo " bin/winapps check"
- echo ""
- echo "If it cannot connect, this is most likely due to:"
- echo " - You need to accept the security cert the first time you connect (with 'check')"
- echo " - Not enabling RDP in the Windows VM"
- echo " - Not being able to connect to the IP of the VM"
- echo " - Incorrect user credentials in winapps.conf"
- echo " - Not merging install/RDPApps.reg into the VM"
- exit
- fi
- done
- if [ $MAKEDEMO = 1 ]; then
- rm -rf /tmp/winapps_demo
- cp -a ${HOME}/.local/share/winapps /tmp/winapps_demo
- exit
- fi
- else
- rm -rf ${HOME}/.local/share/winapps
- cp -a /tmp/winapps_demo ${HOME}/.local/share/winapps
- #sleep 3
- fi
- echo " Finished."
+ echo -n " Checking for installed apps in RDP machine (this may take a while)..."
+ if [ $USEDEMO != 1 ]; then
+ rm -f "$HOME/.local/share/winapps/installed.bat"
+ rm -f "$HOME/.local/share/winapps/installed.tmp"
+ rm -f "$HOME/.local/share/winapps/installed"
+ rm -f "$HOME/.local/share/winapps/detected"
+ cp "$DIR/install/ExtractPrograms.ps1" "$HOME/.local/share/winapps/ExtractPrograms.ps1"
+ # FIXME
+ # shellcheck disable=SC2066
+ for F in "$DIR/apps"; do
+ [[ -e "$F" ]] || break
+ # shellcheck disable=SC1090
+ . "$DIR/apps/$F/info"
+ printf "IF EXIST \"%s\" ECHO %s >> \\\\tsclient\\home\\.local\\share\\winapps\\installed.tmp" "$WIN_EXECUTABLE" "$F" >>"$HOME/.local/share/winapps/installed.bat"
+ done
+ printf "powershell.exe -ExecutionPolicy Bypass -File \\\\tsclient\\home\\.local\\share\\winapps\\ExtractPrograms.ps1 > \\\\tsclient\home\\.local\\share\\winapps\\detected" >>"$HOME/.local/share/winapps/installed.bat"
+ printf "RENAME \\\\tsclient\\home\\.local\\share\\winapps\\installed.tmp installed" >>"$HOME/.local/share/winapps/installed.bat"
+ # shellcheck disable=SC2140
+ $FREERDP_COMMAND /d:"$RDP_DOMAIN" /u:"$RDP_USER" /p:"$RDP_PASS" +auto-reconnect +home-drive -wallpaper +span /app:program:"C:\Windows\System32\cmd.exe",cmd:"/C \\\\tsclient\\home\\.local\\share\\winapps\\installed.bat" /v:"$RDP_IP" 1>/dev/null 2>&1 &
+ COUNT=0
+ while [ ! -f "$HOME/.local/share/winapps/installed" ]; do
+ sleep 5
+ COUNT=$((COUNT + 1))
+ if ((COUNT == 15)); then
+ echo " Finished."
+ echo ""
+ echo "The RDP connection failed to connect or run. Please confirm FreeRDP can connect with:"
+ echo " bin/winapps check"
+ echo ""
+ echo "If it cannot connect, this is most likely due to:"
+ echo " - You need to accept the security cert the first time you connect (with 'check')"
+ echo " - Not enabling RDP in the Windows VM"
+ echo " - Not being able to connect to the IP of the VM"
+ echo " - Incorrect user credentials in winapps.conf"
+ echo " - Not merging install/RDPApps.reg into the VM"
+ exit
+ fi
+ done
+ if [ $MAKEDEMO = 1 ]; then
+ rm -rf /tmp/winapps_demo
+ cp -a "$HOME/.local/share/winapps" /tmp/winapps_demo
+ exit
+ fi
+ else
+ rm -rf "$HOME/.local/share/winapps"
+ cp -a /tmp/winapps_demo "$HOME/.local/share/winapps"
+ #sleep 3
+ fi
+ echo " Finished."
}
function waConfigureApp() {
- if [ -z "${ICON}" ]; then
- ICON=${SYS_PATH}/apps/${1}/icon.${2}
- fi
-
- . "${SYS_PATH}/apps/${1}/info"
- echo -n " Configuring ${NAME}..."
- if [ ${USEDEMO} != 1 ]; then
- ${SUDO} rm -f "${APP_PATH}/${1}.desktop"
- echo "[Desktop Entry]
-Name=${NAME}
-Exec=${BIN_PATH}/winapps ${1} %F
+ if [ -z "$ICON" ]; then
+ ICON=$SYS_PATH/apps/$1/icon.$2
+ fi
+ # shellcheck disable=SC1090
+ . "$SYS_PATH/apps/$1/info"
+ echo -n " Configuring $NAME..."
+ if [ $USEDEMO != 1 ]; then
+ $SUDO rm -f "$APP_PATH/$1.desktop"
+ echo "[Desktop Entry]
+Name=$NAME
+Exec=$BIN_PATH/winapps $1 %F
Terminal=false
Type=Application
Icon=$ICON
-StartupWMClass=${FULL_NAME}
-Comment=${FULL_NAME}
-Categories=${CATEGORIES}
-MimeType=${MIME_TYPES}
-" | ${SUDO} tee "${APP_PATH}/${1}.desktop" >/dev/null
- ${SUDO} rm -f "${BIN_PATH}/${1}"
- echo "#!/usr/bin/env bash
-${BIN_PATH}/winapps ${1} $@
-" | ${SUDO} tee "${BIN_PATH}/${1}" >/dev/null
- ${SUDO} chmod a+x "${BIN_PATH}/${1}"
- fi
- echo " Finished."
+StartupWMClass=$FULL_NAME
+Comment=$FULL_NAME
+Categories=$CATEGORIES
+MimeType=$MIME_TYPES
+ " | $SUDO tee "$APP_PATH/$1.desktop" >/dev/null
+ $SUDO rm -f "$BIN_PATH/$1"
+ echo "#!/usr/bin/env bash $BIN_PATH/winapps $1 $*
+ " | $SUDO tee "$BIN_PATH/$1" >/dev/null
+ $SUDO chmod a+x "$BIN_PATH/$1"
+ fi
+ echo " Finished."
- ICON=""
+ ICON=""
}
function waConfigureApps() {
- APPS=()
- for F in $(cat "${HOME}/.local/share/winapps/installed" | sed 's/\r/\n/g'); do
- . "${DIR}/apps/${F}/info"
- APPS+=("${FULL_NAME} (${F})")
- INSTALLED_EXES+=("$(echo "${WIN_EXECUTABLE##*\\}" | tr '[:upper:]' '[:lower:]')")
- done
- IFS=$'\n' APPS=($(sort <<<"${APPS[*]}"))
- unset IFS
- OPTIONS=("Set up all detected pre-configured applications" "Select which pre-configured applications to set up" "Do not set up any pre-configured applications")
-
- if [ "${INSTALL_TYPE}" != 'User' ]; then
- menuFromArr APP_INSTALL "How would you like to handle WinApps pre-configured applications?" "${OPTIONS[@]}"
- else "grep -l -d skip"
- menuFromArr APP_INSTALL "How would you like to handle WinApps pre-configured applications? If any web browser is set-up, may be configured as default browser." "${OPTIONS[@]}"
- fi
- if [ "${APP_INSTALL}" = "Select which pre-configured applications to set up" ]; then
- checkbox_input "Which pre-configured apps would you like to set up?" APPS SELECTED_APPS
- echo "" >"${HOME}/.local/share/winapps/installed"
- for F in "${SELECTED_APPS[@]}"; do
- APP="${F##*(}"
- APP="${APP%%)}"
- echo "${APP}" >>"${HOME}/.local/share/winapps/installed"
- done
- fi
- ${SUDO} cp "${DIR}/bin/winapps" "${BIN_PATH}/winapps"
- COUNT=0
- if [ "${APP_INSTALL}" != "Do not set up any pre-configured applications" ]; then
- for F in $(cat "${HOME}/.local/share/winapps/installed" | sed 's/\r/\n/g'); do
- COUNT=$((COUNT + 1))
- ${SUDO} cp -r "apps/${F}" "${SYS_PATH}/apps"
- waConfigureApp "${F}" svg
- done
- fi
- rm -f "${HOME}/.local/share/winapps/installed"
- rm -f "${HOME}/.local/share/winapps/installed.bat"
- if (($COUNT == 0)); then
- echo " No configured applications."
- fi
+ APPS=()
+ while IFS= read -r F; do
+ # shellcheck disable=SC1090
+ . "$DIR/apps/$F/info"
+ APPS+=("$FULL_NAME ($F)")
+ INSTALLED_EXES+=("$(echo "${WIN_EXECUTABLE##*\\}" | tr '[:upper:]' '[:lower:]')")
+ done < <(sed 's/\r/\n/g' < "$HOME/.local/share/winapps/installed")
+ # FIXME
+ # shellcheck disable=SC2207,SC2031
+ IFS=$'\n' APPS=($(sort <<<"${APPS[*]}"))
+ unset IFS
+ OPTIONS=("Set up all detected pre-configured applications" "Select which pre-configured applications to set up" "Do not set up any pre-configured applications")
+
+ if [ "$INSTALL_TYPE" != 'User' ]; then
+ menuFromArr APP_INSTALL "How would you like to handle WinApps pre-configured applications?" "${OPTIONS[@]}"
+ else "grep -l -d skip"
+ menuFromArr APP_INSTALL "How would you like to handle WinApps pre-configured applications? If any web browser is set-up, may be configured as default browser." "${OPTIONS[@]}"
+ fi
+ if [ "$APP_INSTALL" = "Select which pre-configured applications to set up" ]; then
+ checkbox_input "Which pre-configured apps would you like to set up?" APPS SELECTED_APPS
+ echo "" >"$HOME/.local/share/winapps/installed"
+ for F in "${SELECTED_APPS[@]}"; do
+ APP="${F##*(}"
+ APP="${APP%%)}"
+ echo "${APP}" >>"$HOME/.local/share/winapps/installed"
+ done
+ fi
+ $SUDO cp "$DIR/bin/winapps" "$BIN_PATH/winapps"
+ COUNT=0
+ if [ "$APP_INSTALL" != "Do not set up any pre-configured applications" ]; then
+ while IFS= read -r F; do
+ COUNT=$((COUNT + 1))
+ $SUDO cp -r "apps/$F" "$SYS_PATH/apps"
+ waConfigureApp "$F" svg
+ done < <(sed 's/\r/\n/g' < "$HOME/.local/share/winapps/installed")
+ fi
+ rm -f "$HOME/.local/share/winapps/installed"
+ rm -f "$HOME/.local/share/winapps/installed.bat"
+ if ((COUNT == 0)); then
+ echo " No configured applications."
+ fi
}
function waConfigureAppsAllOfficiallySupported(){
- ${SUDO} cp "${DIR}/bin/winapps" "${BIN_PATH}/winapps"
- COUNT=0
- for F in $(cat "${HOME}/.local/share/winapps/installed" | sed 's/\r/\n/g'); do
- COUNT=$((COUNT + 1))
- ${SUDO} cp -r "apps/${F}" "${SYS_PATH}/apps"
- waConfigureApp "${F}" svg
- done
- rm -f "${HOME}/.local/share/winapps/installed"
- rm -f "${HOME}/.local/share/winapps/installed.bat"
- if (($COUNT == 0)); then
- echo " No configured applications."
- fi
+ $SUDO cp "$DIR/bin/winapps" "$BIN_PATH/winapps"
+ COUNT=0
+ while IFS= read -r F; do
+ COUNT=$((COUNT + 1))
+ $SUDO cp -r "apps/$F" "$SYS_PATH/apps"
+ waConfigureApp "$F" svg
+ done < <(sed 's/\r/\n/g' < "$HOME/.local/share/winapps/installed")
+ rm -f "$HOME/.local/share/winapps/installed"
+ rm -f "$HOME/.local/share/winapps/installed.bat"
+ if ((COUNT == 0)); then
+ echo " No configured applications."
+ fi
}
function waConfigureDetectedApps() {
- if [ -f "${HOME}/.local/share/winapps/detected" ]; then
- sed -i 's/\r//g' "${HOME}/.local/share/winapps/detected"
- . "${HOME}/.local/share/winapps/detected"
- APPS=()
- for I in "${!NAMES[@]}"; do
- EXE=${EXES[$I]##*\\}
- EXE_LOWER=$(echo "${EXE}" | tr '[:upper:]' '[:lower:]')
- if (
- dlm=$'\x1F'
- IFS="$dlm"
- [[ "$dlm${INSTALLED_EXES[*]}$dlm" != *"$dlm${EXE_LOWER}$dlm"* ]]
- ); then
- APPS+=("${NAMES[$I]} (${EXE})")
- fi
- done
- IFS=$'\n' APPS=($(sort <<<"${APPS[*]}"))
- unset IFS
- OPTIONS=("Set up all detected applications" "Select which applications to set up" "Do not set up any applications")
- menuFromArr APP_INSTALL "How would you like to handle other detected applications?" "${OPTIONS[@]}"
- if [ "${APP_INSTALL}" = "Select which applications to set up" ]; then
- checkbox_input "Which other apps would you like to set up?" APPS SELECTED_APPS
- echo "" >"${HOME}/.local/share/winapps/installed"
- for F in "${SELECTED_APPS[@]}"; do
- EXE="${F##*(}"
- EXE="${EXE%%)}"
- APP="${F% (*}"
- echo "${EXE}|${APP}" >>"${HOME}/.local/share/winapps/installed"
- done
- elif [ "${APP_INSTALL}" = "Set up all detected applications" ]; then
- for I in "${!EXES[@]}"; do
- EXE=${EXES[$I]##*\\}
- echo "${EXE}|${NAMES[$I]}" >>"${HOME}/.local/share/winapps/installed"
- done
- fi
- COUNT=0
- if [ -f "${HOME}/.local/share/winapps/installed" ]; then
- while read LINE; do
- EXE="${LINE%|*}"
- NAME="${LINE#*|}"
- for I in "${!NAMES[@]}"; do
- if [ "${NAME}" = "${NAMES[$I]}" ] && [[ "${EXES[$I]}" == *"\\${EXE}" ]]; then
- EXE=$(echo "${EXE}" | tr '[:upper:]' '[:lower:]')
- ${SUDO} mkdir -p "${SYS_PATH}/apps/${EXE}"
- echo "# GNOME shortcut name
-NAME=\"${NAME}\"
+ if [ -f "$HOME/.local/share/winapps/detected" ]; then
+ sed -i 's/\r//g' "$HOME/.local/share/winapps/detected"
+ # shellcheck disable=SC1091
+ . "$HOME/.local/share/winapps/detected"
+ APPS=()
+ # shellcheck disable=SC2153
+ for I in "${!NAMES[@]}"; do
+ EXE=${EXES[$I]##*\\}
+ EXE_LOWER=$(echo "$EXE" | tr '[:upper:]' '[:lower:]')
+ if (
+ dlm=$'\x1F'
+ IFS="$dlm"
+ [[ "$dlm${INSTALLED_EXES[*]}$dlm" != *"$dlm$EXE_LOWER$dlm"* ]]
+ ); then
+ APPS+=("${NAMES[$I]} ($EXE)")
+ fi
+ done
+ IFS=$'\n' APPS=("$(sort <<<"${APPS[*]}")")
+ unset IFS
+ OPTIONS=("Set up all detected applications" "Select which applications to set up" "Do not set up any applications")
+ menuFromArr APP_INSTALL "How would you like to handle other detected applications?" "${OPTIONS[@]}"
+ if [ "$APP_INSTALL" = "Select which applications to set up" ]; then
+ checkbox_input "Which other apps would you like to set up?" APPS SELECTED_APPS
+ echo "" >"$HOME/.local/share/winapps/installed"
+ for F in "${SELECTED_APPS[@]}"; do
+ EXE="${F##*(}"
+ EXE="${EXE%%)}"
+ APP="${F% (*}"
+ echo "$EXE|${APP}" >>"$HOME/.local/share/winapps/installed"
+ done
+ elif [ "$APP_INSTALL" = "Set up all detected applications" ]; then
+ for I in "${!EXES[@]}"; do
+ EXE=${EXES[$I]##*\\}
+ echo "$EXE|${NAMES[$I]}" >>"$HOME/.local/share/winapps/installed"
+ done
+ fi
+ COUNT=0
+ if [ -f "$HOME/.local/share/winapps/installed" ]; then
+ while read -r LINE; do
+ EXE="${LINE%|*}"
+ NAME="${LINE#*|}"
+ for I in "${!NAMES[@]}"; do
+ if [ "$NAME" = "${NAMES[$I]}" ] && [[ "${EXES[$I]}" == *"\\$EXE" ]]; then
+ EXE=$(echo "$EXE" | tr '[:upper:]' '[:lower:]')
+ $SUDO mkdir -p "$SYS_PATH/apps/$EXE"
+ echo "# GNOME shortcut name
+NAME=\"$NAME\"
# Used for descriptions and window class
-FULL_NAME=\"${NAME}\"
+FULL_NAME=\"$NAME\"
# The executable inside windows
WIN_EXECUTABLE=\"${EXES[$I]}\"
@@ -225,149 +235,154 @@ CATEGORIES=\"WinApps\"
# GNOME mimetypes
MIME_TYPES=\"\"
-" | sudo tee "${SYS_PATH}/apps/${EXE}/info" >/dev/null
- echo "${ICONS[$I]}" | base64 -d | sudo tee "${SYS_PATH}/apps/${EXE}/icon.ico" >/dev/null
- waConfigureApp "${EXE}" ico
- COUNT=$((COUNT + 1))
- fi
- done
- done <"${HOME}/.local/share/winapps/installed"
- rm -f "${HOME}/.local/share/winapps/installed"
- fi
- rm -f "${HOME}/.local/share/winapps/installed.bat"
- if (($COUNT == 0)); then
- echo " No configured applications."
- fi
- fi
+ " | sudo tee "$SYS_PATH/apps/$EXE/info" >/dev/null
+ # shellcheck disable=SC2153
+ echo "${ICONS[$I]}" | base64 -d | sudo tee "$SYS_PATH/apps/$EXE/icon.ico" >/dev/null
+ waConfigureApp "$EXE" ico
+ COUNT=$((COUNT + 1))
+ fi
+ done
+ done <"$HOME/.local/share/winapps/installed"
+ rm -f "$HOME/.local/share/winapps/installed"
+ fi
+ rm -f "$HOME/.local/share/winapps/installed.bat"
+ if ((COUNT == 0)); then
+ echo " No configured applications."
+ fi
+ fi
}
function waConfigureWindows() {
- echo -n " Configuring Windows..."
- if [ ${USEDEMO} != 1 ]; then
- ${SUDO} rm -f "${APP_PATH}/windows.desktop"
- ${SUDO} mkdir -p "${SYS_PATH}/icons"
- ${SUDO} cp "${DIR}/icons/windows.svg" "${SYS_PATH}/icons/windows.svg"
- echo "[Desktop Entry]
+ echo -n " Configuring Windows..."
+ if [ $USEDEMO != 1 ]; then
+ $SUDO rm -f "$APP_PATH/windows.desktop"
+ $SUDO mkdir -p "$SYS_PATH/icons"
+ $SUDO cp "$DIR/icons/windows.svg" "$SYS_PATH/icons/windows.svg"
+ echo "[Desktop Entry]
Name=Windows
-Exec=${BIN_PATH}/winapps windows %F
+Exec=$BIN_PATH/winapps windows %F
Terminal=false
Type=Application
-Icon=${SYS_PATH}/icons/windows.svg
+Icon=$SYS_PATH/icons/windows.svg
StartupWMClass=Microsoft Windows
Comment=Microsoft Windows
-" | ${SUDO} tee "${APP_PATH}/windows.desktop" >/dev/null
- ${SUDO} rm -f "${BIN_PATH}/windows"
- echo "#!/usr/bin/env bash
-${BIN_PATH}/winapps windows
-" | ${SUDO} tee "/${BIN_PATH}/windows" >/dev/null
- ${SUDO} chmod a+x "${BIN_PATH}/windows"
- fi
- echo " Finished."
+ " | $SUDO tee "$APP_PATH/windows.desktop" >/dev/null
+ $SUDO rm -f "$BIN_PATH/windows"
+ echo "#!/usr/bin/env bash
+$BIN_PATH/winapps windows
+ " | $SUDO tee "/$BIN_PATH/windows" >/dev/null
+ $SUDO chmod a+x "$BIN_PATH/windows"
+ fi
+ echo " Finished."
}
function waUninstallUser() {
- rm -f "${HOME}/.local/bin/winapps"
- rm -rf "${HOME}/.local/share/winapps"
- for F in $(grep -l -d skip "bin/winapps" "${HOME}/.local/share/applications/"* -s); do
- echo -n " Removing ${F}..."
- ${SUDO} rm ${F}
- echo " Finished."
- done
- for F in $(grep -l -d skip "bin/winapps" "${HOME}/.local/bin/"* -s); do
- echo -n " Removing ${F}..."
- ${SUDO} rm ${F}
- echo " Finished."
- done
+ rm -f "$HOME/.local/bin/winapps"
+ rm -rf "$HOME/.local/share/winapps"
+ grep -l -d skip "bin/winapps" "$HOME/.local/share/applications/"* -s | while IFS= read -r F
+ do
+ echo -n " Removing $F..."
+ "$SUDO" rm "$F"
+ echo " Finished."
+ done
+ grep -l -d skip "bin/winapps" "$HOME/.local/bin/"* -s | while IFS= read -r F
+ do
+ echo -n " Removing $F..."
+ "$SUDO" rm "$F"
+ echo " Finished."
+ done
}
function waUninstallSystem() {
- ${SUDO} rm -f "/usr/local/bin/winapps"
- ${SUDO} rm -rf "/usr/local/share/winapps"
- for F in $(grep -l -d skip "bin/winapps" "/usr/share/applications/"* -s); do
- if [ -z "${SUDO}" ]; then
- waNoSudo
- fi
- echo -n " Removing ${F}..."
- ${SUDO} rm ${F}
- echo " Finished."
- done
- for F in $(grep -l -d skip "bin/winapps" "/usr/local/bin/"* -s); do
- if [ -z "${SUDO}" ]; then
- waNoSudo
- fi
- echo -n " Removing ${F}..."
- ${SUDO} rm ${F}
- echo " Finished."
- done
+ "$SUDO" rm -f "/usr/local/bin/winapps"
+ "$SUDO" rm -rf "/usr/local/share/winapps"
+ grep -l -d skip "bin/winapps" "/usr/share/applications/"* -s | while IFS= read -r F
+ do
+ if [ -z "$SUDO" ]; then
+ waNoSudo
+ fi
+ echo -n " Removing $F..."
+ "$SUDO" rm "$F"
+ echo " Finished."
+ done
+ grep -l -d skip "bin/winapps" "/usr/local/bin/"* -s | while IFS= read -r F
+ do
+ if [ -z "$SUDO" ]; then
+ waNoSudo
+ fi
+ echo -n " Removing $F..."
+ "$SUDO" rm "$F"
+ echo " Finished."
+ done
}
-if [ -z "${1}" ]; then
- OPTIONS=(User System)
- menuFromArr INSTALL_TYPE "Would you like to install for the current user or the whole system?" "${OPTIONS[@]}"
-elif [ "${1}" = '--user' ]; then
- INSTALL_TYPE='User'
-elif [ "${1}" = '--system' ]; then
- INSTALL_TYPE='System'
+if [ -z "$1" ]; then
+ OPTIONS=(User System)
+ menuFromArr INSTALL_TYPE "Would you like to install for the current user or the whole system?" "${OPTIONS[@]}"
+elif [ "$1" = '--user' ]; then
+ INSTALL_TYPE='User'
+elif [ "$1" = '--system' ]; then
+ INSTALL_TYPE='System'
else
- waUsage
+ waUsage
fi
-if [ "${INSTALL_TYPE}" = 'User' ]; then
- SUDO=""
- BIN_PATH="${HOME}/.local/bin"
- APP_PATH="${HOME}/.local/share/applications"
- SYS_PATH="${HOME}/.local/share/winapps"
- mkdir -p $BIN_PATH
- mkdir -p $APP_PATH
- mkdir -p $SYS_PATH
- if [ -n "${2}" ]; then
- if [ "${2}" = '--uninstall' ]; then
- # Uninstall
- echo "Uninstalling..."
- waUninstallUser
- exit
- elif [ "${2}" = '--setupAllOfficiallySupportedApps' ]; then
- echo "Setting up All Officially Supported Apps "
- echo "Removing any old configurations..."
- waUninstallUser
- waUninstallSystem
- waInstall
- waFindInstalled
- waConfigureWindows
- waConfigureAppsAllOfficiallySupported
- exit
- else
- usage
- fi
- fi
-elif [ "${INSTALL_TYPE}" = 'System' ]; then
- SUDO="sudo"
- sudo ls >/dev/null
- BIN_PATH="/usr/local/bin"
- APP_PATH="/usr/share/applications"
- SYS_PATH="/usr/local/share/winapps"
- if [ -n "${2}" ]; then
- if [ "${2}" = '--uninstall' ]; then
- # Uninstall
- echo "Uninstalling..."
- waUninstallSystem
- exit
- elif [ "${2}" = '--setupAllOfficiallySupportedApps' ]; then
- echo "Setting up All Officially Supported Apps "
- echo "Removing any old configurations..."
- waUninstallUser
- waUninstallSystem
+if [ "$INSTALL_TYPE" = 'User' ]; then
+ SUDO=""
+ BIN_PATH="$HOME/.local/bin"
+ APP_PATH="$HOME/.local/share/applications"
+ SYS_PATH="$HOME/.local/share/winapps"
+ mkdir -p "$BIN_PATH"
+ mkdir -p "$APP_PATH"
+ mkdir -p "$SYS_PATH"
+ if [ -n "$2" ]; then
+ if [ "$2" = '--uninstall' ]; then
+ # Uninstall
+ echo "Uninstalling..."
+ waUninstallUser
+ exit
+ elif [ "$2" = '--setupAllOfficiallySupportedApps' ]; then
+ echo "Setting up All Officially Supported Apps "
+ echo "Removing any old configurations..."
+ waUninstallUser
+ waUninstallSystem
+ waInstall
+ waFindInstalled
+ waConfigureWindows
+ waConfigureAppsAllOfficiallySupported
+ exit
+ else
+ usage
+ fi
+ fi
+elif [ "$INSTALL_TYPE" = 'System' ]; then
+ SUDO="sudo"
+ sudo ls >/dev/null
+ BIN_PATH="/usr/local/bin"
+ APP_PATH="/usr/share/applications"
+ SYS_PATH="/usr/local/share/winapps"
+ if [ -n "$2" ]; then
+ if [ "$2" = '--uninstall' ]; then
+ # Uninstall
+ echo "Uninstalling..."
+ waUninstallSystem
+ exit
+ elif [ "$2" = '--setupAllOfficiallySupportedApps' ]; then
+ echo "Setting up All Officially Supported Apps "
+ echo "Removing any old configurations..."
+ waUninstallUser
+ waUninstallSystem
- echo "Installing..."
- waInstall
- waFindInstalled
- waConfigureWindows
- waConfigureAppsAllOfficiallySupported
- exit
- else
- usage
- fi
- fi
+ echo "Installing..."
+ waInstall
+ waFindInstalled
+ waConfigureWindows
+ waConfigureAppsAllOfficiallySupported
+ exit
+ else
+ usage
+ fi
+ fi
fi
echo "Removing any old configurations..."
diff --git a/kvm/RDPWindows.xml b/kvm/RDPWindows.xml
index 1523b9c..4a7e227 100644
--- a/kvm/RDPWindows.xml
+++ b/kvm/RDPWindows.xml
@@ -208,4 +208,3 @@
+385601105:+385600513
-
diff --git a/install/RDPApps.reg b/oem/RDPApps.reg
similarity index 100%
rename from install/RDPApps.reg
rename to oem/RDPApps.reg
diff --git a/oem/install.bat b/oem/install.bat
new file mode 100644
index 0000000..182423c
--- /dev/null
+++ b/oem/install.bat
@@ -0,0 +1,3 @@
+@echo off
+
+REG IMPORT C:\OEM\RDPApps.reg