ssue

As more and more companies move their MyDocs–which are normally stored on a file share–to OneDrive for Business, organizations run into issues with OneNote notebooks. What follows is a little background information into the problem. Many organizations are not utilizing the OneNote sync feature for OneNote notebooks but instead are using the file share to peruse OneNote content. Once OneNote files are moved to OneDrive for Business, the OneDrive for Business replication service is used to replicate OneNote notebooks. The problem with using the OneDrive for Business replication service and not the OneNote replication service is the OneNote notebook cannot be accessed across all platforms. The OneNote IOS app does not know how to open a OneNote notebook stored in the OneDrive for Business IOS app. When a OneNote notebook is opened from the OneDrive for Business IOS app, the OneNote notebook is opened as an attachment to a blank OneNote notebook.

From our testing to solve the problem of accessing a OneNote notebook across all platforms, OneNote, OneNote Online, and the OneNote IOS app, the sync mechanism has to be converted from ODFB (.one file replicated to the cloud via the ODFB sync client) to OneNote sync (the OneNote notebook is converted to a URL).

The challenge we uncovered is end-users would be responsible for converting the OneNote notebook sync method. End-users would need to know the URL path to their notebook (when using Office 2010) and need to enter the network location as:

https://domainname-my.sharepoint.com/personal/XXXXX.domain.com/documents/OneNote Notebooks/NAME OF NOTEBOOK

Asking end-users to configure URLs for each workbook is unreasonable and overwhelming. To mitigate this issue, we created a script that converts all OneNote notebooks to use the OneNote sync method.

The script opens the OneNote Notebook in OneNote Online via IE. The opening and closing of each OneNote Notebook in IE is hidden from the end-user, thus executing this task in the background. The reason that each Notebook is open and closed in IE is because, the OneNote Notebook is marked as recently accessed from the OneNote IOS app. Having a OneNote Notebook show up as recently accessed allows the end-users to open their OneNote Notebooks from the  OneNote IOS app.

Requirements

  • This script only works in environments with AD FS and on computers that are domain joined. I have another version of the script that would work with password sync with AAD Connect
  • This script only works with Office 2010 & 2016. It can be easily configured to work with Office 2013
  • AD FS URLs must be added into the trusted zones within IE
  • Computers must have Internet access

OneNote File Location

The location of OneNote notebooks are stored in two locations: the registry and a cache file ending with .onecache.

C:\Users\<user>\AppData\Local\Microsoft\OneNote\<version>

Windows stores the  location of the notebooks in the registry (HKCU\Software\Microsoft\Office\14.0\OneNote\OpenNotebooks)    

Script

One of the first actions performed is to capture the user’s UPN. This is used later to build the HTTP URL for the ODFB site.

The OneNote application is closed to allow for Regkeys to be changed and the cache file to be renamed.

The cache file is then renamed to today’s date. This also allows for the recovery of any cache content that has not been saved to OneNote.

The OneNote notebooks Regkey are stored in the PathOneNote variable. The PathOneNote variable looks something like C:\User\<UserName>\OneDrive – <domain>\<OneNote location>. In our lab environment it would look like C:\Users\Janet\OneDrive – CB5-Lab\OneNote\CB5. We want to remove OneNote\CB5 and leave the notebook name.

The next bit of code checks to see if the notebook is already using OneNote sync.

The code below updates the Regkey to use the OneNote.

Once the Regkey has been updated, IE will be open to that OneNote location. The OneNote notebook is opened in the background and the end-user should not see IE open and close. We are using the inputtext information to enter the username and password for portal.office.com (line 178 and 180).

End User Experience

Depending on the number of OneNote files, the script can take up to 20 minutes for users with ~100 notebooks.

The script will close any open OneNote files and IE pages. Once OneNote has been closed, the script will start the process of converting the files.

The end-user will be required to select the ribbon on all workbooks to start the sync process with Office 365.

End-users will need to select their usernames from the Office 365 window. This is a one-time action; all other workbooks will sync with Office 365 after this is completed once.

The workbook and notebooks will be opened from OneNote

After the Script is Executed

The OneNote cache file will be renamed to the date and time the script was run.

Note: Microsoft does not recommend renaming the cache file – link\link\link\link.

The registry keys have been updated to now use the OneNote sync method.

Log File

A log file is created under $logfile
= ($env:APPDATA
+
“\OneNote.log”).
The log file can be used to track the actions being performed by the script.


Script

Currently the script only works with Office 2010 & 2016. It is relatively easy, however, to get Office 2013 working by finding the version 14 in the script and changing it to 15.

Search for DomainName in the syntax below and replace it with your SharePoint Online tenant name.


$logfile = ($env:APPDATA + "\OneNote.log") 
#The URL variables are used to replace the OneNote notebook regkey from pointing at the file system to pointing at the ODFB URL
#Each URL variable makes up part of the URL
$URL1 = "Https://DomainName-my.sharepoint.com/personal/"
$URL3 = "/documents\"
$URL316 = "/documents"
$SharePointNoteBookURL = "Https:"
$SharePointNoteBookURL16 = "-my.sharepoint.com"
$Close = "https://login.microsoftonline.com/logout.srf"
$BaseURL = "https://login.microsoftonline.com/"
function log{
param (
[String]$text,
[Switch]$fout
)
ac $logfile $text
if($showConsoleOutput){
if($fout){
Write-Host $text -ForegroundColor Red
}else{
Write-Host $text -ForegroundColor Green
}
}
}
$scriptPath = $MyInvocation.MyCommand.Definition
log -text "-----$(Get-Date) OneNote - $($env:USERNAME) on $($env:COMPUTERNAME) starting-----" 
#The data is what we are using to set the extension of the cache file or cache folder
$Time = Get-Date -format h.m.M.d.yyyy
$CacheName14 = "OneNoteOfflineCache.onecache.$time"
$CacheName16 = "cache.$time"
#Determine the OneNote version installed on the computer
$Version = Get-ItemProperty -Path HKCU:\Software\Microsoft\Office\16.0\OneNote\OpenNotebooks -ErrorAction SilentlyContinue -ErrorVariable ProcessError | ft '1' -HideTableHeaders
If ($ProcessError) {
log -text "------ Office 2016 is not installed"
$ProcessError = $null 
}
$IntVersion = ($version).Count
if ($v -gt '1')
{
$OneNoteVersion = "16.0"
$OfficeVersion = "Office16"
log -text "------ Office 2016 is installed" 
}
Else {
$OneNoteVersion = "14.0"
$OfficeVersion = "Office14"
log -text "------ Office 2010 is installed" 
}
# $UPN = user1@domain.com
$upn = whoami /upn
log -text "------ User Account $UPN" 
#Since the ODFB user uses user1_domain_com, we replace the @ and . to _
$UPN1 = ($upn).Replace("@","_")
$URL2 = ($UPN1).Replace(".","_")
log -text "------ URL2 $URL2" 
#Stop OneNote
$OneNote = Get-Process OneNote -ErrorAction SilentlyContinue -ErrorVariable ProcessError
If ($ProcessError) {
log -text "------ Couldn't access the OneNote Process"
$ProcessError = $null 
}
if ($OneNote) {
# try gracefully first
try{
$OneNote.CloseMainWindow()
$OneNoteM.CloseMainWindow()
}catch{ 
log -text "------ One of the OneNote process wasn't running"
} 
# kill after five seconds
Sleep 5
if (!$oneNote.HasExited) {
$Onenote | Stop-Process -Force
$OneNoteM |Stop-Process -Force 
}
}
Start-Sleep -s 30
#Rename cache file to .today's date for OneNote 2010 or rename the cache folder for OneNote 2016 to .today's date
If ($OneNoteVersion -eq "14.0") {
$LocalAppData = $env:LOCALAPPDATA
$OneNote = "\Microsoft\OneNote\14.0\OneNoteOfflineCache.onecache"
Rename-Item -Path "$LocalAppData$OneNote" -NewName $CacheName14 -ErrorAction SilentlyContinue -ErrorVariable ProcessError
If ($ProcessError) {
log -text "------ Couldn't rename the cache file"
$ProcessError = $null 
}
Else {
log -text "------ File path $LocalAppData$OneNote"
log -text "------ Rename Cache file $CacheName14"
}
}
Else {
$LocalAppData = $env:LOCALAPPDATA
$OneNote = "\Microsoft\OneNote\16.0\cache"
Rename-Item -Path "$LocalAppData$OneNote" -NewName cache.$time
If ($ProcessError) {
log -text "------ Couldn't rename the cache file"
$ProcessError = $null 
}
Else {
log -text "------ File path $LocalAppData$OneNote"
log -text "------ Rename Cache file $CacheName16"
}
}
If ($OneNoteVersion -eq "14.0") {
#Loop through to determine how many workbooks are open. We can change the value from 100 to any number
for($i=0
$i -le 100){
#Export the property of the open OneNote notebooks
$PathOneNote = Get-ItemProperty -Path "HKCU:\Software\Microsoft\Office\$OneNoteVersion\OneNote\OpenNotebooks" | ft "$i" -HideTableHeaders | Out-String
#$PathOneNote = $PathOneNote.trim()
$PathOneNote = $PathOneNote.trim()
#Remove the ODFB path and only leave the OneNote Path (standard OneNote path c:\users\OneDrive - Domain\OneNote) This command removes c:\users\OneDrive - Domain & leaves \OneNote. 
if($PathOneNote -like '*OneDrive - DomainName *'){
$URL4Root = $PathOneNote -replace ".*OneDrive - DomainName"
log -text "------ OneNote path full name $PathOneNote"
log -text "------ Remove OneDrive - DomainName $URL4Root"
#Remove whitespace
$URL4PlaceHold = $URL4Root.trim()
log -text "------ Remove whitespace $URL4PlaceHold"
$URL4RemoveDash = $URL4PlaceHold.Substring(1)
log -text "------ Remove dash $URL4RemoveDash"
$URL4 = $URL4RemoveDash }
ElseIf($PathOneNote -gt " ") {
$URL4 = $PathOneNote.trim()
log -text "------ OneNote path short name $PathOneNote" 
}
Else {
$URL4 = ""
} 
 
#Combind all the URLs
$URL = "$URL1$URL2$URL3$URL4" 
#Find any OneNote notebooks that have already been synced with SharePoint Online
$SharePointNoteBook = $url4.split("/")
#Check to make sure the notebook is synced with SharePoint Online
If ($SharePointNoteBook -contains $SharePointNoteBookURL) {log -text "------ Notebook is already synced using OneNote $SharePointNoteBookURL"}
ElseIF ($URL4 -gt " "){
#Change the OneNote regkey to point to the ODFB URL and not the file system
#write-host "URL1 - " $URL1
#write-host "URL2 - " $URL2
#write-host "URL3 - " $URL3
#write-host "URL4 - " $URL4
#write-host "URL - " $URL
log -text "------ URL1 $URL1" 
log -text "------ URL2 $URL2"
log -text "------ URL3 $URL3"
log -text "------ URL4 $URL4"
log -text "------ Full URL Path $URL" 
set-ItemProperty -Path "HKCU:\Software\Microsoft\Office\$OneNoteVersion\OneNote\OpenNotebooks" -Name "$i" -Value $URL
log -text "------ Updateed note book $i with value $URL"
#Open IE so the notebooks show up within the iOS version of OneNote 
$NB1URL = "$URL1$URL2"
$NB2URL = "/_layouts/OneNote.aspx?id=%2fpersonal%2f"
$NB3URL = "$URL2"
$NB4URL = "%2fdocuments%2f"
$NB5URL = $URL4.Replace("\","%2f")
$NB6URL = "&"
$NBURL = "$NB1URL$NB2URL$NB3URL$NB4URL$NB5URL$NB6URL"
log -text "------ NB1URL $NB1URL"
log -text "------ NB2URL $NB2URL"
log -text "------ NB3URL $NB3URL"
log -text "------ NB4URL $NB4URL"
log -text "------ NB5URL $NB5URL"
log -text "------ NB6URL $NB6URL"
log -text "------ NBURL Full Path $NBURL"
Try {
#Get-Process iexplore | Foreach-Object { $_.CloseMainWindow() }
Get-process iexplore -ErrorAction SilentlyContinue | Stop-Process
$ie = New-Object -com internetexplorer.application
$ie.navigate($Close)
$ie.visible = $False
Start-sleep 15
$ie.navigate($NBURL)
$ie.visible = $False
Start-sleep 5
$ie.document.IHTMLDocument3_getElementById("cred_userid_inputtext").value = $UPN
Start-Sleep 5
$ie.document.IHTMLDocument3_getElementById("cred_password_inputtext").click() 
Start-Sleep 20
$ie = ""
$ie = New-Object -com internetexplorer.application
} 
Catch
{
log "------ Notebook $NBURL failed"
} 
}
$i++
}
}
Else {
#Loop through to determine how many workbooks are open. We can change the value from 100 to any number
for($i=0
$i -le 100){
#Export the property of the open OneNote notebooks
$PathOneNote = Get-ItemProperty -Path "HKCU:\Software\Microsoft\Office\$OneNoteVersion\OneNote\OpenNotebooks" | ft "$i" -HideTableHeaders | Out-String
#Remove the ODFB path and only leave the OneNote Path (standard OneNote path c:\users\OneDrive - Domain\OneNote) This command removes c:\users\OneDrive - Domain & leaves \OneNote.
#$StrPathOneNotePath = Split-Path -Leaf $PathOneNote
if($PathOneNote -like '*OneDrive - DomainName*'){
$URL4Root = $PathOneNote -replace ".*DomainName "
log -text "------ OneNote path full name $PathOneNote"
log -text "------ Remove OneDrive - DomainName $URL4Root"
#Remove whitespace
$URL4PlaceHold = $URL4Root.trim()
log -text "------ Remove whitespace $URL4PlaceHold"
$URL4RemoveDash = $URL4PlaceHold.Substring(1)
log -text "------ Remove dash $URL4RemoveDash"
$URL4 = $URL4RemoveDash }
ElseIf($PathOneNote -gt " ") {
$URL4 = $PathOneNote.trim()
log -text "------ OneNote path short name $PathOneNote" 
}
Else {
$URL4 = ""
} 
 
#Combind all the URLs
$URL = "$URL1$URL2$URL3$URL4" 
#Find any OneNote notebooks that have already been synced with SharePoint Online
$SharePointNoteBook = $url4.split("/")
#Check to make sure the notebook is synced with SharePoint Online
If ($SharePointNoteBook -contains $SharePointNoteBookURL) {log -text "------ Notebook is already synced using OneNote $SharePointNoteBookURL"}
ElseIF ($URL4 -gt " "){
#Change the OneNote regkey to point to the ODFB URL and not the file system
#write-host "URL1 - " $URL1
#write-host "URL2 - " $URL2
#write-host "URL3 - " $URL3
#write-host "URL4 - " $URL4
#write-host "URL - " $URL
log -text "------ URL1 $URL1" 
log -text "------ URL2 $URL2"
log -text "------ URL3 $URL3"
log -text "------ URL4 $URL4"
log -text "------ Full URL Path $URL" 
set-ItemProperty -Path "HKCU:\Software\Microsoft\Office\$OneNoteVersion\OneNote\OpenNotebooks" -Name "$i" -Value $URL
log -text "------ Updateed note book $i with value $URL"
#Open IE so the notebooks show up within the iOS version of OneNote 
$NB1URL = "$URL1$URL2"
$NB2URL = "/_layouts/OneNote.aspx?id=%2fpersonal%2f"
$NB3URL = "$URL2"
$NB4URL = "%2fdocuments%2f"
$NB5URL = $URL4.Replace("\","%2f")
$NB6URL = "&"
$NBURL = "$NB1URL$NB2URL$NB3URL$NB4URL$NB5URL$NB6URL"
log -text "------ NB1URL $NB1URL"
log -text "------ NB2URL $NB2URL"
log -text "------ NB3URL $NB3URL"
log -text "------ NB4URL $NB4URL"
log -text "------ NB5URL $NB5URL"
log -text "------ NB6URL $NB6URL"
log -text "------ NBURL Full Path $NBURL"
Try {
#Get-Process iexplore | Foreach-Object { $_.CloseMainWindow() }
Get-process iexplore -ErrorAction SilentlyContinue | Stop-Process
$ie = New-Object -com internetexplorer.application
$ie.navigate($Close)
$ie.visible = $False
Start-sleep 15
$ie.navigate($NBURL)
$ie.visible = $False
Start-sleep 5
$ie.document.IHTMLDocument3_getElementById("cred_userid_inputtext").value = $UPN
Start-Sleep 5
$ie.document.IHTMLDocument3_getElementById("cred_password_inputtext").click() 
Start-Sleep 20
$ie = ""
$ie = New-Object -com internetexplorer.application
} 
Catch
{
log "------ Notebook $NBURL failed"
} 
}
$i++
}
}
#starts OneNote again for the user
Start-process -Filepath "C:\Program files (x86)\Microsoft Office\$OfficeVersion\onenote.exe" -ErrorAction SilentlyContinue -ErrorVariable ProcessError
If ($ProcessError) {
log -text "------ Couldn't Start OneNote"
$ProcessError = $null 
ElseIf {
log -text "------ OneNote Started"
}
}
{}
Get-process iexplore -ErrorAction SilentlyContinue | Stop-Process
log -text "------------------- $Time End of Script -------------------"