Introduction:
The Windows 365 Preview application is a great store app for organizations utilizing Windows 365 virtual desktops. Although currently, there is no “official” way to bypass the first run experience. From what I’ve heard, Microsoft says there may be some more options for this once the app is GA, but there is no timeline for this. I was bored one night and wanted to see if there was a way to bypass the App’s first run experience. By first run experience, I’m referring to the four pages we have to click through when the app is launched for the first time (GIF below if you aren’t familiar). An added bonus would be if we could remove the quick action “take the tour” tile. In the end, I did find a way to skip the first run experience, but it’s difficult to deploy in bulk, and unless you really really want to skip the first run experience, it’s probably more trouble than it’s worth. Hopefully, Microsoft releases an official easy way to bypass this in the future. Regardless, this was fun, I learned some things throughout the process. You can also learn a bit about procmon and how to do some detective work in this post. So, here’s how we can skip the first run experience in the Windows 365 app.
Here’s the First Run Experience I am referring to:
The Windows 365 app is currently in preview and is available for both Windows 10 and 11 from the Microsoft Store:
Detective Work:
With most Windows-based apps, I figured this was probably a registry key that gets flipped. That should be easy enough to track down. I’ve covered this in previous blogs, but my tool of choice to find before and after registry changes is RegistryChangesView by Nirsoft. We can take a snapshot of all reg hive keys before doing something, and then grab a snapshot after doing something. This will show us any added keys and any changed values. So, I grabbed a snapshot after installing the Windows 365 Preview App, and then grabbed another snapshot after going through the first run experience. Not much happened, but initially, I thought I found the value I needed on my first try. A value name of “WasEverActivated” was created with a value of 1. See below:
I felt like I got lucky, and this would be an easy solution, but it wasn’t. I tested changing that value to 0 and also deleting the value completely, but I could not trigger the first run experience again. Since I had already gone through the first run experience, the goal of this exercise was to reverse the change and have the first run experience re-occur. If I could do that, then I’d know what needed to be changed. I proceeded through the other added or modified registry values by deleting multiple at a time to narrow down the possible culprits. However, no registry values resulted in re-triggering the first run experience. So, the registry was not controlling the first run experience.
Next, I fired up procmon to see what is happening after the first run experience is complete. Procmon can be messy since there is so much going on, so I recommend you learn how to use the filters. Even with filters, there can still be a lot to go through. Since I already ruled the registry out, I filtered registry items and some other things out of procmon, and focused the results on file system changed from the Windows365.exe process name.
Next, I fired up procmon to see what is happening after the first run experience is complete. Procmon can be messy since there is so much going on, so I recommend you learn how to use the filters. Even with filters, there can still be a lot to go through, but you can narrow your results easily by adding additional filters to the results. Since I already ruled the registry out, I filtered registry items along with some others and focused the results of the Windows365.exe process name.
Next, I installed the Windows 365 application while letting procmon run, and proceeded through the first start pages. That still resulted in 11,000+ file system events. I started skimming through the events to see if anything looked interesting. There were some files and folders created in the %localappdata% data directory for the signed-in user account that looked interesting. I narrowed my filter to CreateFile to I could see what was being created and where. This brought the results down to 1900, but the %localappdata%\Packages\MicrosoftCorporationII.Windows365_8wekyb3d8bbwe looked particularly interesting, so I applied one more filter for anything created with that file path. This brought my results down to 190:
I opened that LocalCache Directory and started poking around. There were some additional directories in here timestamped at the time I launched the software for the first time. Oddly, procmon didn’t show any additional files or subdirectories created here, but more on that later.
Since these were created at first launch and I wanted to reproduce the first run experience, I figured I’d start at the top level and delete everything in the LocalCache directory, then relaunch the app to see if I could retrigger the first-time run experience. Low and behold, authentication to the app and the first-time run experience had to be redone:
Now that we have our directory, we needed to determine the file or files that contain this data. I started opening files with recognizable file formats and looking through the folders. On first thought, the accounts and settings.json looked interesting. The accounts.json file contains the user data that authenticated to the app. Deleting that file will force you re-authenticate the next time the app is launched. Settings.json contained no additional interesting data. There was too much to manually go through, so I started deleting child folders to find which child folder would give me the result I wanted. The WebView2 folder was the culprit, so I opened that to take a closer look:
This directory contained a single directory named EDWebView with a bunch of sub-directories:
Many of these directories were empty or contained very small files. There were some .json files in the AutoLaunchProtocolsCompont directory, but those proved to have no effect. I started deleting a few folders at a time, then relaunching the app until I could reproduce the first-time run experience. After a few minutes, I narrowed it down to the Default folder, which also contained numerous sub-directories:
I repeated the process and a few minutes later narrowed in on the Local Storage directory, which contained one sub-directory named leveldb:
There were a handful of files in this folder:
After some more process of elimination, the file I’ve been looking for is the 000003.log file. Let’s pop it open and look at it. This is not a traditional log file we expect with a .log extension. It looks like this contains some metadata for the connection to Windows 365. There are some interesting entries in here. I’m not certain if “FRE” pertains to “First Run Experience”, but I am assuming it does. This is the file AFTER I already proceeded through the first run experience:
The other interesting thing here is the Windows365 process is not creating or writing to this file. It creates the top level LocalCache folder at %localappdata%\Packages\MicrosoftCorporationII.Windows365_8wekyb3d8bbwe\LocalCache, which we identified with Procmon. But a different process is creating the sub-directories and files. If we delete everything under the LocalCache folder, and then re-launch the Windows 365 app while monitoring that location with ProcMon, we can identify that the Windows365 app is calling on the msedgewebview2.exe process, which creates a slew of additional files, including our 000003.log file:
Per Microsoft (Introduction to Microsoft Edge WebView2 – Microsoft Edge Development | Microsoft Learn), MSEdgewebview2 allows you to embed web technology into apps. Essentially, this is using Edge to display web content in Windows 365 application. So, the first run experience, along with a bunch of other content is really not part of the app code, but displaying web content via the msedgewebview2 process. It seems the metadata and other contents contained in the 000003.log file determine which web content is shown to the user. Let’s do more testing. This time, I removed the application and then reinstalled it. I want to see what the 000003.log file looks like before finishing the first run experience, and what gets added when as we progress through:
Here is the file after simply launching the Windows 365 app (before signing in or doing anything else):
And after signing in to the app, but before the first run experience is completed, we can see a portion of the user’s account ID and also a value of “shouldRunFREOnWindows”:”true”:
Now let’s proceed through the first run experience. There was no change to the file after proceeding through the first run experience. However, additional writes happen to this file after closing the application. Here is the file after we close the app with additional data added at the bottom, and we can see “ShouldRunFREOnWindows”:”false”
If we re-open the app and then close it once more, it looks like some more data gets added, but it doesn’t look interesting. It basically logs the time the app was closed.
Next, let’s re-open the app, close the tile to “Take the tour”, and then close the app and see what our 000003.log file looks like.
Here is the additional data added to the file, and we can see an entry for {“shouldRunFREOnWindows”:”false”,”dismissedQuickActions”:”{\”-749878783\”:[\”TOUR\”]}”,”_persist”:” that was added as a result of closing the Quick Action tour tile:
For good measure, if we open the app and close it once more, we can confirm no first run experience, no Take the Tour tile, and we get a simple entry into the .log file with the time we closed the app:
Now that we have identified some of the file contents, let’s create a template file with the proper data to skip the FRE and try moving it to another device. There are a few things to know about this:
- Remember the full directory path for the 000003.log file does not exist until the Windows365 app is launched the first time
- Creating this directory path BEFORE installing the Windows 365 app will result in it being deleted when the app gets installed. So, the directory path must be created and the log file placed in the proper location after the app is installed.
Here is the file I am going to use. I simply installed the Windows365 app on a device, signed in, went through the FRE, and closed the tour tile. Notice the FRE is set to “false” and there is data after dismissedQuickActions after closing that tile.
Moving it over to another PC by Installing the Windows 365 app, creating the levelDB directory, and then placing the log file there resulted in a successful no first-time run experience. However, I was using the same account to sign in on this device as I did on the device where I copied the 000003.log file. You don’t see a cloud PC show up for this user when I recorded the GIF because I had since removed the license for this user. I only have one trial license and I assigned it to another user to test if it would work across different users.
Next, I need to see if I can skip this if a different user signs in to the App. I was skeptical of this since part of the Account ID is located in the .log file. This time, I follow the same process, but sign in with a different user account to the Windows 365 app. This also successfully skips the first run experience:
What’s interesting about the results for a different user account signing in is the First Run Experience does not happen, but the Take the Tour Tile shows up. Not a big deal, but let’s open the log file and look. Here is the log file after we signed in, which still contains the tour tile. The new portion added to our original file is highlighted, and I point out the Account ID of the new user account. The app still sees the “false” flag and did not run the first run experience.
Next, I cleared the tour tile as this user, and then checked to see what changed in the log file. This is where it all made more sense. The new entry at the bottom shows what we’ve seen before, only this time an additional value of “551063579” is added to the “dismissquickactions”, which removes the quick actions Tour tile. This looks like some kind of identifier for the user accounts that have cleared the tile. I’ve highlighted the original entry and the new entry at the bottom:
So, we can get rid of the first run experience for everyone, but we can’t get rid of the Quick Action Tour Tile, which isn’t that big of a deal.
Deployment
Let’s look at some ways we can actually deploy this if we really really wanted to. The way it is now, it’s probably more trouble than it’s worth, honestly. So, hopefully Microsoft makes this much easier in the future. But if you are determined, I walk through how to deploy with Intune using Win32Apps. There are definitely other ways to do this, but the difficulty is making sure the app is installed, and then creating the leveldb directory, and copying the log file to the target devices before they launch the app for the first time. You can also use proactive remediations, but those run on a schedule and you’d need your log file available in a repository to download. Or, you can use an RMM similarly to a proactive remediation unless it has a way to deliver a file payload to devices. Anyway, here’s how to use a couple of Win32 apps to get this all deployed:
First, Deploy the Windows 365 Preview app using the Microsoft Store App (New) deployment method. You’ll see this is a UWP installer. So, we can’t make a win32app dependent on this application type.
Next, we need to make a dummy Win32app that simply checks to see if the Windows 365 app is installed. I say it’s a dummy app because its only purpose is to detect the installation of the Windows 365 application. This will allow us to make our real Win32 app dependent on this one, which ends up creating the %localappdata%\Packages\MicrosoftCorporationII.Windows365_8wekyb3d8bbwe\LocalCache\WebView2\EBWebView\Default\Local Storage\leveldb directory and copies our 000003.log file to that location.
Here is our dummy Win32 app to check if the Windows 365 app is installed. We use a custom detection script like below to verify the app exists:
Our custom detection script is simple:
$Win365 = Get-AppPackage -Name '*Windows365*'
If ($Win365) {
Write-Output "Windows365 App Detected"
Exit 0
}
else {
exit 1
}
We can see this app showing in the dashboard as installed:
Next, we need to make our Win32app that creates the %localappdata%\Packages\MicrosoftCorporationII.Windows365_8wekyb3d8bbwe\LocalCache\WebView2\EBWebView\Default\Local Storage\leveldb directory and copies our 000003.log file which is configured to skip the first run experience.
Here is our install script:
$Path = "$env:LOCALAPPDATA\Packages\MicrosoftCorporationII.Windows365_8wekyb3d8bbwe\LocalCache\WebView2\EBWebView\Default\Local Storage\leveldb"
$Exists = Test-Path -Path $Path
If ($Exists -eq $False){
New-Item -Path $Path -ItemType Directory
Copy-Item -Path ".\000003.log" -Destination $Path
}
else {
Write-Output "Directory and Log already exist"
}
Wrap the install script and the 000003.log file as a .intunewin file:
Create a new Win32 app with the following details:
For our detection rule, we are using a simple file detection rule to see if the 000003.log file exists in %localappdata%\Packages\MicrosoftCorporationII.Windows365_8wekyb3d8bbwe\LocalCache\WebView2\EBWebView\Default\Local Storage\leveldb\. We do this because if that file already exists, we are assuming this app has already been launched and someone has skipped the first run experience already. Ideally, if we autopilot our machine, the Windows 365 app will be installed, our dummy detection Win32 app will detect its installed, and this app will create the necessary directory to house the 000003.log file, so it exists before the user launches the application for the first time.
And we also make this app dependent on our previous Win32 app that simply checks to see if the Windows 365 app is installed:
Let’s make sure it worked:
And on our target device, we see the directory was created and the log file is there. We can tell the app hasn’t been launched yet since there is no other data in that directory.
And for good measure, if we launch the app and sign in, we can verify there is no first-run experience: