Microsoft documentation describes how to customize the Start menu, the only issue is that this will reset the pinned apps each time the device syncs back to Intune. For the use case where you want to set the initial start menu configuration and then allow the user to pin their own apps is not currently available. But in this blog post we will do just that, set initial start menu configuration, and allow the user to change it afterwards.
There have been multiple other blog post around this, but after testing out a lot of them I have had no success. I tried setting registry values, I tried applying the LayoutModifciation.json and I tried to copy the start.bin file, all failed in one way or another. Copying of the start.bin file failed due to the profile being created during enrollment did not use the start.bin from the default Windows profile, and when I tried to copy it to all users on the device it would simply not copy it to the current user that the device was being deployed to. I ended up using a way of copying the start.bin file with a combination of creating a schedule task, this way I always get the correct start menu instantly.
Customize the Start menu layout on Windows 11
When you customize the Start layout, you overwrite the entire full layout. A partial Start layout isn’t available. Users can pin and unpin apps, and uninstall apps from Start. When a user signs in or Explorer restarts, Windows reapplies the MDM policy. This action restores the specified layout and doesn’t retain any user changes.
Preparing your Start Menu
How to pin and unpin apps to the Start menu
Prepare the way you want your Start Menu to look like on a Windows 11 device.
Worth mentioning is that if you have devices that are being deployed on a Windows build less then 22H2 then you will need to have two versions of the start.bin file. Windows Build 22H2 uses a file named start2.bin instead of start.bin.
The way I did this was by setting up a fresh VM with Windows 11 build 21H2, I then removed the pinned apps that I did not want and added the once that I wanted.
Next, I ran Windows update and installed the Windows 11 22H2 build, this will generate the second start2.bin once restarted.
Exporting the start.bin file(s)
The start.bin files are located in your user profile.
Full location: %LocalAppData%\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState
Copy the start.bin and start2.bin file into a folder, we will need these later on.
PowerShell Script to copy files and create scheduled task
This is the script I use to copy the correct start.bin file and deploy it during the enrollment process, you may want to modify this as I create some folder where I store the files, you may want to use the temp folder etc.
The part that will make this work is the schedule task. The GroupId I use in this task is the Default Users group in Windows. This part is what makes it able to copy the files to the current user during the enrollment process.
Save the script as install.ps1 in the same folder you placed your start.bin file(s)
If ($ENV:PROCESSOR_ARCHITEW6432 -eq "AMD64") {
Try {
&"$ENV:WINDIR\SysNative\WindowsPowershell\v1.0\PowerShell.exe" -File $PSCOMMANDPATH
}
Catch {
Throw "Failed to start $PSCOMMANDPATH"
}
Exit
}
if (!(Test-Path "$env:SystemDrive\ProgramData\AutoPilotConfig\Start-Menu")) {
New-Item -ItemType Directory -Path "$env:SystemDrive\ProgramData\AutoPilotConfig\Start-Menu"
}
$Destination = "$env:SystemDrive\ProgramData\AutoPilotConfig\Start-Menu"
# Check Windows Build to copy start.bin or Start2.bin depending in build number
$BuildNumber=[INT](Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | Select-Object -ExpandProperty CurrentBuildNumber)
If ($BuildNumber -lt 22621) {
$Source = "$PSScriptRoot\start.bin", "$PSScriptRoot\StartMenu.ps1"
Copy-Item -path $Source -Destination $Destination -Force
}
else {
$Source = "$PSScriptRoot\start2.bin", "$PSScriptRoot\StartMenu.ps1"
Copy-Item -path $Source -Destination $Destination -Force
}
# Define the principal
$principal = New-ScheduledTaskPrincipal -GroupId "S-1-5-32-545" -RunLevel Highest
# Define the task settings
$taskSettings = New-ScheduledTaskSettingsSet `
-AllowStartIfOnBatteries `
-DontStopIfGoingOnBatteries `
-ExecutionTimeLimit (New-TimeSpan -Hours 72)
# Define the task trigger
$taskTrigger = New-ScheduledTaskTrigger -Once `
-At (Get-Date).AddSeconds(5)
# Define the task action
$taskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File $Destination\StartMenu.ps1"
# Register the scheduled task
Register-ScheduledTask -TaskName "StartMenu" `
-TaskPath "\" `
-Principal $principal `
-Settings $taskSettings `
-Trigger $taskTrigger `
-Action $taskAction `
-Force
As you can see the script refers to a StartMenu.ps1 and we will create this next. This is used to trigger the copy of the file to the current user during the enrollment.
StartMenu.ps1 (The file the scheduled task runs)
StartMenu.ps1 copy’s the file to the current user profile. I’m using Stop-Process to restart the StartMenuExperienceHost.exe, if this is not done then the user will have to restart the device one time before seeing the new Start Menu layout.
Save the StartMenu.ps1 file in the same folder you placed your start.bin file(s)
If ($ENV:PROCESSOR_ARCHITEW6432 -eq "AMD64") {
Try {
&"$ENV:WINDIR\SysNative\WindowsPowershell\v1.0\PowerShell.exe" -File $PSCOMMANDPATH
}
Catch {
Throw "Failed to start $PSCOMMANDPATH"
}
Exit
}
#Copy Start.bin file(s) to folder
Copy-Item -Path "$env:SystemDrive\ProgramData\AutoPilotConfig\Start-Menu\*.bin" -Destination "$env:UserProfile\AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\" -Force -Verbose
#Delay
Start-Sleep -Seconds 10
#Restart Start Menu Experince
Stop-Process -Name StartMenuExperienceHost -Force
Packaging the files as a Win32 application
You should now have a folder with two start.bin files (start.bin and start2.bin), the folder should also contain the install.ps1 and the StartMenu.ps1 file.
We will use the Microsoft Win32 Content Prep Tool to package the files.
- Start the Microsoft Win32 Content Prep Tool as Administrator
- Select the location where stored your files.
- Specify the setup file: install.ps1
- Select the folder where you want the output.
- The file .intunewin will contain all the files you had in the folder.
- A file named install.intunewin should now have been created.
Deploy the package using Intune
Go to Intune and select Apps, Add a new Win32-based app.
Add the package that we just created install.intunewin
Add a name, description, Publisher, Version etc.
Program settings
Install command: powershell -executionpolicy bypass -file install.ps1
Install behavior: System
Requirements
Detection rules
For this I just made it simple, it only verifies that the files being copied are in the location we wanted them to be. If you modify the script, make sure you modify the detection rules. (I know this is not really checking if the full process was completed, but you can modify this or add create register files depending on success or failure.)
Rule type: File
Path: %SystemDrive%\ProgramData\AutoPilotConfig\Start-Menu
File or folder: start.bin
Detection method: File or folder exist
Assign the newly created app to “All users” as Required (This will overwrite any current user settings they have, so you can assign it to only new users if you like)
Custom Detection script, checks the file and task (UPDATE)
Instead of using the detection rules mentioned above you can use this detection script, this is going to verify that the files are create and the scheduled task is also created.
If you edited anything in the script, please edit the detection script to fit your need.
Add the app as Required to the Enrollment Status page profile
Go to your enrollment status page and make sure you add the app to the required apps, this will make sure it will be deployed during the enrollment.
You are done.
When a new device is deployed, the start menu layout will be instantly applied for the end-user and they can then pin their own apps.
Extra
In my script I do not delete the task, you could call it at a later stage if needed. If you want it to be deleted, you can always add something like the below, this would delete the task.
# Wait for the task to finish running
Start-Sleep -Seconds 180
# Delete the scheduled task
Unregister-ScheduledTask -TaskName "StartMenu" -TaskPath "\" -Confirm:$false
So this installed really fine on my already enrolled work PC, with the only downside being the Powershell window popping up.
However, the start menu layout is not applied if the app is installed during ESP device setup step. Via company portal I see that the app was successfully installed. I guess that it is applied before the user account is created.
You could use a cmd file instead of PowerShell, this way you wont have the PowerShell prompt.
I use this during ESP with success. You could add an extra delay if it takes to long time. Also verify that the files are copied, if the start.bin files are in the right location then I believe it’s an delay issue for you.
I’m having a similar issue, I see that the app installed successfully but the modified time on the start.bin file is not changing. So for some reason, the start.bin file in the app is not overriding the one created on the user’s initial login. Any ideas on how to address that? I’ve just published the app to the company portal and run it after the user logs in., but it would be great to automate this.
Will it overwrite when you run the scheduled task?
I will re-test during the weekend and see if I can replicate the issue. Both on first deployed user and then on second user login.
To hide the powershell popup:
Replace this in install.ps1. The WindowStyle Hidden quickly hides the popup, barely noticeable this way.
Hi, do you know if this works on your user profiles? I’d really appreciate it.
Yes this is on the user profiles
This is not working for me however it is worth saying I am only using Windows 11 Pro 22H2 so I only have one start2.bin file and not a start.bin since all my network is 22H2 or above do I still need a start.bin ?
You only need one.
Start.bin will only be copied if the version of Windows is below 22H2, start2.bin will be copied if its 22H2.
Check the following on the device you are applying it to.
1. Is the Start2.bin copied to the folder: ProgramData\AutoPilotConfig\Start-Menu.
2. Is the StartMenu Task Schedule created, and when was it last triggered?
3. Check the user profiles Start2.bin in UserProfile\AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState\ what is the last modified date of the file?
If the files are in the correct place, try triggering the Schedule Task manually and see if the start menu is applied.
I just tested the package again in a brand new machine and everything is working, it is being applied during the enrollment for the user that is signing in during the Account Setup process.
Just copy the file here and all (new) users will get the start layout :
C:\Users\Default\AppData\Local\Packages\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\LocalState
This can be added to the script but it wont show up for the first user being deployed.
Interesting, I did notice it’s not working well. The file is copied fine, but not applied it seems. Do you know why this is?
Please check of the schedule task is created and run it again to see if it is applied. This is being deployed to multiple devices each day without any issues. Please also make sure the date of the start.bin in the profile you copy it to have the same date as you the start.bin you generated
Sorry, I meant to ask if you know why just copying the file does not work? Your workaround solution works great, thank you.
I really do not know why it does not work, I dont know if its how the user profiles are created during OOBE.
First…I’m no PS expert but can typically figure stuff out. What I don’t understand is how the packaged intunewin app will have access to the start2.bin file I exported. Does the Win32 App Creation tool automatically package the start2.bin file from the source folder where the app is created? ($Source = ”$PSScriptRoot\start2.bin) ?
Nowhere in this process did I designate the start2.bin file to be used.
You mention a temp folder above, which may address this but it may be over my head.
Love your site!
I will update that part later this week. Will also update the script so it works with pre-provisioning.
But if you place the script files and start.bin files etc all in the same folder and then run the win32 app packager it will create the intunewin file and it will contain all the files that was in the folder.
Thank you for commenting
I finally got this to work and it works perfectly. I had my startmenu.ps1 script named incorrectly bc the one I downloaded saved as startmenu-2.ps1 or something. Got that fixed.
Beyond the scope here but as an intune noob I am also finding that intune doesn’t respond super quickly even when just making changes to a policy. Sometimes you have to wait an hour or more for the policy change to be effective after you save it. I made a change, did a new Autopilot deployment about 30 min later to test it. No bueno. I thought my corrections were bunk.
Then…the script ran an hour-plus after the initial deployment. I saw the foreground output and the 10-second delay language, lol ! all of a sudden it was perfect. like I’d run the script myself. My hunch is that it will work on the next deployment now that my corrections have ‘taken’. But MAN that is frustrating about Intune. Iterative testing takes monumental amounts of time.
That great, i will update so the file downloads with the correct name, it is always the easy things you spend the most time on 😁
This worked a charm, thanks very much!
One thing I was wondering however, we have a URL shortcut for a SIP address to dial in Teams. I created this on the machine I wanted to deploy the Start Menu to and it pins every app bar this one. Is it possible to package something like this in Intune?
Yes that would work, however you would need to have the shortcut created/deployed. You can do this as a seperate app or ad it to this package, add the shortcut on the ropt folder, in the code where we copy tha start.bin files add a new line where you copy the shortcut to your location, make sure the start.bin file where you pinned the shortcut have the same path. This should work, but I have not tested this.
Do I have to set the $PSScriptRoot myself in the install script? And if yes what folder do I use?
No you dont, this will check the root folder from where the script is running from, so if you keep all files in the same folder then it works.
Thank you, we tried it and it works, but the installation fails when we add the app to the ESP profile. Still figuring out what the problem is.
Can you check if the folders are created and files are in place and schedule task is created even if it fails? Put some logging to the script so it outputs the log to a file. I deployed this with and without admin users and in pre-provisoning also.
Maybe check the detection rules also so they are correctly set if you are using the detection script.
How can I change an entry afterwards? Like Microsoft splitTeams to ”Classic” and ”New”. I have enrolled ”Classic” back then but now have to change it to ”New” without the user have to re-do their customized Start Menu
You can repackage the script with your changes as new win32 app and push it out to overwrite the changes.
This is also not working for us for during OOBE with Intune. The behavior is the script will run before the user first signs in (during OOBE provisioning), and therefore the start menu task is run while the appdata\local\packages folder does not exist. The user signs in and the start menu is not configured, no surprise there. Intune reports it as install success.
I made quite a few changes to add a file detection script to intune that corrects this. The detection looks for a separate file in the packages folder during install. If it can’t find it, it retries, which is what we needed. Install success/ failure reporting is now accurate in Intune.
Not sure where to upload these suggested changes but a few tweaks in Install.ps1 and StartMenu.ps1 were necessary in addition to the detection script change.
Please post a link to your revised version, never had issues with this but i guess the timing can be off and if you found a more stable way i would love to add that in here.
I posted the link as a reply here but I don’t see it. Does the reply need to be approved?
Strange I have approved all comments from you
We’re having this same issue. I’d love to see your additions too.
This worked perfectly for me, thanks for your work, although I have a slight issue, with which I’m hoping you’ll be able to help. The script only worked for the person that was initially logged in to the PC. I asked another person to log-in, and unfortunately it didn’t work for him, the start menu icons were still default. Any suggestions, so it runs every time when new user logs in? Thank you.
I will test this scenario later, but it should work if the app is set to required install for all users