Story
I have written dedicated PowerShell scripts to backup and restore my Outlook signatures. Per the instructions provided on the script home page, I store a copy of the scripts in a folder in OneDrive, so that when I backup my signatures, they are automatically synched to OneDrive, and when I want to restore the latest signatures from another machine (or on a fresh new Windows installation), I can run the restoration script, which will automatically trigger downloading of (a.k.a. ‘recall’) the latest backup if they are not already available offline (a.k.a. ‘online’ in terms of Hierarchical Storage Management).
On my machines, I configure Windows PowerShell execution policy as AllSigned and use a self-signed certificate for local code signing. I chose to not sign these copies of scripts, and instead use a shortcut (.lnk file) to open PowerShell with execution policy overridden as Unrestricted. It is simple enough to create a shortcut to powershell.exe -ExecutionPolicy Unrestricted with its ‘Start in’ (initial working directory) set to the empty string. When you double-click (i.e., invoke the default verb open on) the shortcut, the initial working directory of the started PowerShell instance will be the folder File Explorer was showing, i.e., the folder where the shortcut resides. I can sync the shortcut to OneDrive, and double-click it any time I would like on any machine with my OneDrive synched.
It is important to set the initial working directory to the empty string, since the actual path where the shortcut lives varies among machines. For example, on my personal computer, this is usually C:\Users\GL\OneDrive\Documents\OutlookSignatures, while on the working station at Microsoft, this was C:\Users\<alias>\OneDrive\Documents\OutlookSignatures. Generally, it would be a bad idea to assume the shortcut lives in %USERPROFILE%\OneDrive\Documents\OutlookSignatures, because the OneDrive sync folder can be changed. If the initial working directory of the shortcut is empty, it will default to the lpDirectory
field of the SHELLEXECUTEINFO
structure passed into ShellExecuteEx
function, which will be the directory where the shortcut resides if it is opened from File Explorer.
However, this perfect solution didn’t survive OneDrive On-Demand mechanism, which we shall detail in the following sections.
Issue
Condition
- You have created a shortcut to powershell.exe with empty ‘Start in’ directory. The file is placed on local storage.
- You double-click the shortcut to launch it. Then you close the newly started PowerShell instance.
- You copy the shortcut to a OneDrive sync folder, have it synched to OneDrive, and then set it as ‘Available when online’ (the file becomes offline, having FILE_ATTRIBUTE_OFFLINE attribute) by invoking ‘Free up space’ context menu command.
- You double-click the shortcut to launch it. This recalls the file (makes it ‘Available on this device’) and launches a PowerShell instance. Then you close the newly started PowerShell instance.
- You double-click the shortcut to launch it again. This time there is no need to recall the file. Then you close the newly started PowerShell instance.
Symptoms
- In step 2, the newly launched PowerShell instance has the local folder where the shortcut resides as the initial path.
- In step 4, the newly launched PowerShell instance has the current directory of File Explorer as the initial path, which typically is C:\Windows\System32.
- In step 5, the newly launched PowerShell instance has the OneDrive folder where the copy of the shortcut resides as the initial path.
Expected behaviours
In step 4, the newly launched PowerShell instance should have the OneDrive folder where the copy of the shortcut resides as the initial path. This is expected since availablity of the file should be transparent to the user when the user is connected to the Internet and OneDrive is running, albeit the speed.
Workaround
Currently, I use the following batch instead of a shortcut to replace its functionality in my scenario:
@CD /D %~dp0
@START "PowerShell: Outlook Signatures Prompt" powershell.exe -ExecutionPolicy Unrestricted
Details
Environment
- Windows 10 version 1803 build 17134.191
- OneDrive app version 18.111.0603.0006 synching a OneDrive Personal library, or OneDrive app version 18.151.0729.0001 synching a OneDrive Personal / OneDrive for Business library (I did not have the opportunity to test version 18.111 on OneDrive for Business library)
- Windows PowerShell version 5.1.17134.165
Reproduction
- Create a shortcut to powershell.exe, then set its ‘Start in’ (initial working directory) in its Properties to the empty string. That the ‘Start in’ directory of the shortcut is empty is crucial to the reproduction of this issue.
- Copy the shortcut to a OneDrive folder (say it is now C:\Users\UserName\OneDrive\ps.lnk), wait for it to sync, and then right-click it and choose ‘Free up space’. Make sure it is now ‘Available when online’.
- Start Windows PowerShell, and run the following commands:
[System.Environment]::CurrentDirectory = 'C:\Windows\System32'
# The current directory of this PowerShell process is now
# C:\Windows\System32
Start-Process C:\Users\UserName\OneDrive\ps.lnk -WorkingDirectory 'C:\Users\UserName\OneDrive'
# The above line recalls the shortcut and launches it, but
# WorkingDirectory does not take effect. That line will open
# the shortcut with ShellExecuteExW, exactly the same way how
# it is launched when double-clicked in File Explorer.
#
# RESULT: a new PowerShell instance starts in
# C:\Windows\System32
Start-Process C:\Users\UserName\OneDrive\ps.lnk -WorkingDirectory 'C:\Users\UserName\OneDrive'
# Repeat, starting with an "Available on this device" file.
#
# RESULT: a new PowerShell instance starts in
# C:\Users\UserName\OneDrive
Notes
The above PowerShell commands can be replaced by opening the shortcut twice, the first time an ‘Available when online’ file, the second time an ‘Available on this device’ file.
The way we invoke Start-Process
will eventually lead us to the code path using ShellExecuteExW
. You can read the source code of this command to find out more. Here is a hint.
Solution
Microsoft should fix the code when ShellExecut
ing an offline (‘Available when online’) shortcut.
Moral
Usually this section is the lesson we should learn from this issue. But today in this entry, I would like to talk about HSM. It is noticeable that Microsoft no longer ships Hierarchical Storage Management with Windows since Windows Server 2008. However, a similar functionality is now widely used by everyday users of Windows like you and me, in the form of OneDrive On-Demand files. I wonder whether Windows 8.1 OneDrive sync engine uses the same technique, or is the Windows 10 OneDrive On-Demand sync engine a good revamp that revives HSM. I think they’re different. In Windows 8.1, if you get disconnected from the Internet, your online-only files are hidden by the sync engine, while in Windows 10 you don’t get that weirdo.
Some interesting blog entries by Raymond Chen you should read:
- Taxes: Hierarchical Storage Management
- What triggers the recall of an offline file?
- Taxes redux: You can’t open the file until the user tells you to open it
- Why don’t I get thumbnails for files that are marked offline?
Some facts about HSM are no longer true about OneDrive On-Demand files. For example, OneDrive sync engine acts as the thumbnail handler and fetches thumbnails from OneDrive service, even the file is not recalled. However, some rules still apply for OneDrive On-Demand files scenario. New apps should keep in mind that they might be working with OneDrive On-Demand files. I am worrying most about photo management applications that scan the whole library by opening each file for inspection during their first run, which will cause a catastrophe as my 135 GB photo library will be recalled. You might have noticed that OneDrive sync engine leaves two fixes for that: one is that you can suppress an app from triggering automatic downloads, but your app might crash or something if you do this; the other is that you can choose to not put stub files (placeholders) for some folders by unselecting them for sync in OneDrive app settings.
I once heard from Leon Zhou that iCloud on macOS can be set to speculatively upload least recently used personal files and later purge them as the disk space goes narrow. These files can be recalled on demand.
Please enable JavaScript to view the comments powered by Disqus.