Pass an URL parameter to a SharePoint Online form’s field

The only way to pass a URL parameter to a SharePoint Online (modern design) form’s field is to use PowerApps (at least, if you cannot add any JS on your website!).

Important warning: when you use PowerApps to manage your form, all edits to the list settings won’t reflect to the PowerApps form. For example, if you add a field, it won’t show up, and you’ll have to manually update the PowerApps to add it (see at the bottom of this article).

From the list view, go to Integrate then PowerApps and Customize forms:

Once PowerApps has open the form, you need to do several things.

1. Load the ID

We first need to make sure the form will load the required item when we pass the ID URL parameter:

From the SharepointForm Advanced Settings, we change the DefaultMode to check if we have the ID parameter, and if we don’t have it, then it should be a New Form, otherwise an Edit Form:

If(IsBlank(Param("ID")), FormMode.New, FormMode.Edit)

From the SharepointForm Advanced Settings, we change the Item section to check if we have the ID parameter, and if we have it, then we do a lookup in our list to find the data:

If(IsBlank(Param("ID")), SharePointIntegration.Selected, LookUp('NAME OF THE LIST', ID = Value(Param("ID"))))

Add a SUBMIT button

With PowerApps, there is no button to save the changes! We’ll add a button in the form:

In the button’s properties, we change the onSelect to be:

SubmitForm(SharePointForm1)

Be aware that the page will stay with the form after clicking on the button. You could want to close using the Exit() function, but the user will be redirected on office.com … I’d recommend to use Launch() by redirecting your users to a page:

SubmitForm(SharePointForm1); Launch("https://tenant.sharepoint.com/sites/MySite/");

Set field’s value based on URL parameter

We can finally set the field’s value based on the parameter in the URL. Select the INPUT zone of the field, and in the Default section we use the below formula:

If(IsBlank(Param("Title")), ThisItem.Title, Param("Title"))

Here my field is called “Title” so I decided to use a parameter called “Title” as well.

Link to the form

We cannot use the NewForm.aspx or EditForm.aspx to access this form, but we need a special link.

Go to your list settings:

Then go to the form settings (it’s from there that you can decide to keep PowerApps or use the original Sharepoint Forms), and click on See versions and usage:

You’ll get the App Id from this page:

Next, you’ll use the App Id to forge the URL: https://apps.powerapps.com/play/providers/Microsoft.PowerApps/apps/APP_ID
With our example, the URL will be: https://apps.powerapps.com/play/providers/Microsoft.PowerApps/apps/c6f23ac1-dcbd-4daf-925e-2701ab241ca0

You can now pass the URL parameter: https://apps.powerapps.com/play/providers/Microsoft.PowerApps/apps/APP_ID?Title=Hello%20World
And an ID to retrieve an existing item: https://apps.powerapps.com/play/providers/Microsoft.PowerApps/apps/APP_ID?Title=Hello%20World&ID=2

How to use it with a LookUp column?

If you want to auto-select a LookUp field using an URL parameter, you need to do a few things…

First, we need to add the related table. To do so, click on Data in the left navigation bar and search for SharePoint:

Search for the table and add it.

Second (optional) step: click on the Lookup field in the form and change the Items to show a list of options – if no “Lookup” ID in the URL, then we use the default list of options:

The below formula permits to retrieve the “ID” and “Title” from the distant list, base on the “Lookup” parameter, and to rename the result as {Id:"ID", Value:"Title"}:

If(IsBlank(Param("Lookup")), Choices([@'CURRENT LIST NAME'].COLUMN_NAME), RenameColumns(ShowColumns(Filter('DISTANT LIST NAME', ID = Value(Param("Lookup"))), "ID", "Title"), "ID", "Id", "Title", "Value"))

Third, click on the Lookup field in the form and change the DefaultSelectedItems to select the item from the list of options:

The below formula returns an empty selection with {Id:"", Value:""} when no URL param, otherwise it returns the first record for our lookup:

If(IsBlank(Param("Lookup")), {Id:"", Value:""}, First(RenameColumns(ShowColumns(Filter('DISTANT LIST NAME', ID = Value(Param("Lookup"))), "ID", "Title"), "ID", "Id", "Title", "Value")))

And finally, we can pass Lookup=ID in the URL to select the related item in the other list

How to deal with new fields?

If you add a new field to your list’s settings, you’ll have to edit the form in PowerApps, and then edit the fields and add the new one:

(I used this article as a starting point)

Transfer an Alexa AWS Lambda function from the online editor to the ASK CLI

When we follow the guide to build a new smarthome skill, it gives the steps to create a function in the online code editor.

But if you prefer to use the ASK CLI, there is some steps to follow…

I first create a fake skill with ask new (using the “hello world” and “AWS Lambda” options).

Once the folder structure and files are created, I edit the .ask/ask-states.json file to reflect the information from the skill I created during the guide.

Then in the folder skill-package I remove everything except skill.json. To find what to put into that file, use the command: ask smapi get-skill-manifest -s <SKILL ID> and copy/paste that code.

Finally, I force the deploy with ask deploy --ignore-hash.

The Lambda function can now be managed locally on your computer and deployed with ASK CLI. You can go to the different skill consoles to delete the fake skill “hello world” you created.

Add a domain to a Let’s Encrypt certificate

For Apache, in the folder sites-available, you need to create your the-new-one.your-domain.com.conf file. Then enable the new site with a2ensite the-new-one.your-domain.com.

You can list all domains associated with a certificate:

certbot certificates

Now we add the SSL using certbot. You need to list all the existing domains and add the new one:

certbot --apache --cert-name your-domain.com -d first.your-domain.com,second.your-domain.com,third.your-domain.com,the-new-one.your-domain.com

Get email address from a Azure DevOps “by” field in Power Apps Flow

If you need to get an email from an Azure DevOps work item (e.g. from the “Changed By” field), it might be tricky in Power Apps Flow because it will return “John Doe <john@doe.com>”.

To only extract the email from this string, you’ll have to use the below:

first(split(last(split([YOUR_FIELD],'<')),'>'))

Use CTRL and TAB to switch between two tabs in Chrome

It’s super handy to be able to switch between two tabs in the web browser… But it’s tricky to set it up in Chrome!

  1. Install AutoControl: Keyboard shortcut, Mouse gesture
  2. Install the native component as the extension asks for
  3. Add a new action
  4. The trigger is LEFT CTRL and TAB
  5. The action is Switch to previous tab

It should now work to switch between tabs using LEFT CTRL + TAB.

Mise à jour d’un serveur Kimsufi (OVH) depuis Debian 10 (Buster) vers Debian 11 (Bullseye)

Il faut régulièrement penser à mettre à jour son serveur Kimsufi.

Je vais essayer d’expliquer brièvement les étapes à suivre pour cela.

  1. On vérifie les problèmes liés à la mise à jour.
  2. Prévoir une connexion SSH depuis 2 emplacements si possible à cause d’un problème sur SSH durant l’installation.
  3. On va effectuer une mise à jour des paquets avec apt-get update && apt-get upgrade
  4. On va sauvegarder les données :
    mkdir /root/svg_special; cp -R /var/lib/dpkg /root/svg_special/; cp /var/lib/apt/extended_states /root/svg_special/; dpkg --get-selections "*" > /root/svg_special/dpkg_get_selection; cp -R /etc /root/svg_special/etc
  5. Ensuite il est conseillé d’utiliser screen pour pouvoir se reconnecter (avec screen -r) à en cas de déconnexion :
    screen
  6. Le processus de mise à niveau décrit sur le site de Debian a été conçu pour des mises à niveau des systèmes « purs » sans paquet provenant d’autres sources. Pour une meilleure fiabilité du processus de mise à niveau, vous pouvez supprimer ces paquets du système avant de commencer la mise à niveau :
    aptitude search '~i(!~ODebian)'
  7. On peut éventuellement purger les vieux paquets obsolètes. Pour cela on va d’abord les lister, puis on peut les purger si tout semble bon:
    aptitude search '~o'
    aptitude purge '~o'
  8. On peut lancer la commande dpkg --audit pour s’assurer que tout est bon avant la migration. On peut également taper dpkg --get-selections "*" | more et vérifier qu’aucun paquet n’est en on hold
  9. Maintenant il faut remplacer tous les “buster” de /etc/apt/sources.list par des “bullseye” (on pourra par exemple utiliser sed -i 's/buster/bullseye/g' /etc/apt/sources.list)

    On vérifiera aussi les fichiers qui se trouvent dans /etc/apt/sources.list.d, en modifiant par exemple la source pour MariaDB.

    J’ai également dû remplacer la ligne deb http://security.debian.org/ bullseye/updates main contrib non-free de mon fichier /etc/apt/sources.list par deb http://security.debian.org/debian-security bullseye-security main contrib non-free.

  10. Il est recommandé d’utiliser le programme /usr/bin/script pour enregistrer une transcription de la session de mise à niveau. Ainsi, quand un problème survient, on a un enregistrement de ce qui s’est passé. Pour démarrer un enregistrement, taper :
    script -t 2>~/upgrade-buster.time -a ~/upgrade-buster.script
  11. On passe aux choses sérieuses, en commençant par mettre à jour les listes des paquets :
    apt-get update
  12. On va vérifier qu’on a la place suffisante (un message explicite apparait sinon) :
    apt -o APT::Get::Trivial-Only=true full-upgrade
  13. On va maintenant faire une mise à jour minimale :
    apt-get upgrade
  14. Et à partir de là le système va vous questionner… en général choisir l’option par défaut si vous ne savez pas quoi répondre
  15. Puis on continue avec
    apt full-upgrade

Cette dernière étape va durer un certain temps. Une fois terminé, vous pouvez redémarrer le serveur pour s’assurer que tout va bien.

Il est bien de vérifier que la version actuelle de PHP est correctement utilisée par Apache et qu’elle correspond à ce qu’on veut. Pour cela on vérifie la version avec:

php -v

Ensuite on regarde les versions de PHP disponibles dans les modules d’Apache :

ls -l /etc/apache2/mods-available/php*

Et on regarde celle activée :

ls -l /etc/apache2/mods-enabled/php*

On regarde également dans le dossier des modules pour vérifier quelle version on a :

ls -l /etc/apache2/modules/libphp*

Si la version souhaitée est manquante dans les modules, alors on l’installe, par exemple pour la 7.4 :

apt-get install php7.4 php7.4-mysql

On s’assure ensuite de bien activer la bonne version, par exemple en passant de la v7.0 à v7.4 :

a2dismod php7.0
a2enmod php7.4

Et on redémarre Apache :

systemctl restart apache2

Une fois les erreurs corrigées, on va nettoyer tous les paquets avec :

apt-get autoremove

Note : pour arrêter screen on fait CTRL + A puis k.

Portable version of NodeJS on Windows

(This is a corrected version of this blog post)

  1. Install Cmder in your desired location.
  2. Download nvm-noinstall.zip from the latest release.
  3. Extract the contents of nvm-noinstall.zip (i.e.: nvm.exe …) into the bin folder inside of the portable Cmder folder.
  4. Navigate to the bin.
  5. Create a new file called install_fix.cmd that contains this code.
  6. Open a terminal in the bin folder and type .\install_fix.cmd
  7. When asked to enter the path use the full path to your Cmder bin folder.
  8. If it worked, a file called settings.txt has been created in the your Cmder bin folder.
  9. Close the terminal, and reopen it in the bin folder.
  10. Install the version of Node you want, e.g. nvm install latest.
  11. Wait until the installation is completed, then, inside the bin folder, there should be a new folder containing the latest Node version (e.g. v17.3.0).

From there, you can use the full path to your Cmder bin + the Node version folder + node.exe to execute something with this version of Node using Powershell, CMD or other terminal.

For example:

PS D:\experiments\my-stuff\> D:\experiments\nodejs-portable\cmder_mini\bin\v17.3.0\node.exe index.js

You could use Cmder with the Node path in the Startup Settings of the app; e.g. set "PATH=D:\experiments\nodejs-portable\cmder_mini\bin\v17.3.0;%PATH%". This way, in Cmder, when typing node.exe it’s the portable version that will be used.

Redirect non-www to www on a PHPBB Forum

In the PHPBB directory, edit the file .htaccess and after RewriteRule ^(.*)$ app.php [QSA,L] you can enter:

RewriteCond %{HTTPS} off
# First rewrite to HTTPS:
# Don't put www. here. If it is already there it will be included, if not
# the subsequent rule will catch it.
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Now, rewrite any request to the wrong domain to use www.
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Debug a third party Android APK

(inspired by this blog post)

1) Install smalidea plugin

Download the smalidea plugin (see also the related Github Repository).

Open up Android Studio and you should see the welcome screen like the one on screenshot below (if not, close your current project by selecting File -> Close project), go to the Plugins section, and from the wheel icon, select Install Plugin from Disk.... Select the smalidea plugin (ZIP file) you downloaded.
Android Studio welcome screen

2) Get the third party APK

You first need to know the type of platform where you’ll do your debug tests. To do so, make sure your device is connected to your computer (it could also be a virtual device started from the AVD Manager) with adb devices.
Then, use the command adb shell getprop ro.product.cpu.abi to find the type of processor you have. When I use my phone, I got arm64-v8a.

Go to an APK platform, like https://apkcombo.com/ and search for the Android app you want to debug. Download the APK version that fits to the type you found before:
screenshot of https://apkcombo.com/

2bis) Have a look at the APK content

You can use JADX to open the APK and have a quick look at the code.

3) Decompile APK

With APKTool, we’ll use the command: .\apktool.bat d ".\the_original_app_from_apkcombo.com.apk" -o app_to_debug.
A folder called app_to_debug is created with the decompiled version of the application.

Next, we need to copy the source files: create a folder called “src” in the new app_to_debug folder, and type cp -R smali*/* src/.

4) Import project in Android Studio

Open an existing Android Studio project and select the app_to_debug folder where you unpacked APK.

Once the project loads, you need to tell the IDE where is your source code. Make sure you’re using the “Project view” in the left side panel:

Now you can see folder structure in your left panel. Find src/ subfolder right click it and select Mark Directory as -> Sources Root.

5) Prepare App for Debugging

Open AndroidManifest.xml from the app_to_debug and find the XML element <application>. Add the attribute android:debuggable with value “true”. Example:

<application android:debuggable="true" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:largeHeap="true" android:name="org.horaapps.leafpic.App" android:theme="@style/Theme.AppCompat">

6) Repack to APK

You can now repack to APK with the command .\apktool.bat b -d ".\app_to_debug\" -o app_unsigned.apk

7) Sign the APK

7a) Create a keystore

You first need a keystore using keytool and type the below command:
keytool -genkeypair -v -keystore mykey.keystore -alias mykey -keyalg RSA -keysize 2048 -validity 10000

Several questions you’ll be asked, as well as a password. Make sure to remember the password for later.

7b) Validate the APK

You then need zipalign that can be found in the Android SDK folder (e.g. C:\Users\USERNAME\AppData\Local\Android\Sdk\build-tools\31.0.0\zipalign.exe) to validate your APK:
.\Path\to\Android\Sdk\build-tools\31.0.0\zipalign.exe -f -v 4 .\app_unsigned.apk .\app_ready.apk

7c) Sign the APK

Finally you can sign the new created APK with apksigner:
.\Path\to\Android\Sdk\build-tools\31.0.0\apksigner.bat sign --ks .\mykey.keystore --ks-key-alias app_to_debug --out .\app_signed.apk .\app_ready.apk

8) Install the APK

You can install it using adb install app_signed.apk

9) Prepare the host

On your Android device, go to Settings -> Developer options and set USB debugging and Wait for debugger options on. The latter is optional but useful as it allows you wait for debugger connection and not to run app yet.

Finally, you should tap on Select debug app and choose the app you just installed. After all of these, your Developer options menu should look somewhat like this:

Now, launch the app on the Android device, and you’ll get the below message:

10) Forward debugger port

You can use the adb’s port forwarding feature and forward JDWP service where application’s debug interface is listening.

Find the JDWP port with the command adb jdwp, then use this port with the command:
adb forward tcp:5005 jdwp:JDWP_PORT

11) Connect Debugger

Go to Android Studio and from its top menu bar choose Run -> Debug…, then a small message appears with one unique option that is Edit Configurations.... There, in the window, use a plus (+) button at the opt left, and add a new configuration of type Remote. Leave the default configuration as is. Click the Debug button and your app should be running with the attached debugger which means it will stop once a breakpoint is hit and you can investigate the content of app’s variables.