Office 365 or office 2019 install using ODT set it and forget it

Thanks Jason,
but this is the section that is not working, and yes the redirect.txt file does exist.
assigning the relevance to a parameter, I get a parameter add failed.

parameter “SourceDownload”="{(it, following text of last “/” of it | it) of node values of attributes “href” of xpaths (“xmlns:xhtml=‘http://www.w3.org/1999/xhtml’”, “//xhtml:a[@class=‘mscom-link failoverLink’]” ) of xml document of file “C:\temp\DownloadODT\redirect.txt”}"

I thought we’d addressed that issue in an earlier post in this thread

I tried your code, but I get an error “evaluation error” relevance clauses must be surrounded by { and } guards.
but you had provided guards in the code, so I am not sure where it wants the guards added.

parameter “SourceDownload”=”{node value of attribute “href” of xpath (“xmlns:xhtml=‘http://www.w3.org/1999/xhtml’”, “//xhtml:a[@class=‘mscom-link failoverLink’]” ) of xml document of file “C:\temp\DownloadODT\redirect.txt”}"

Can you post the first ten lines or so from the downloaded file C:\temp\DownloadODT\redirect.txt ?

I’d like to check whether the file was replaced by a proxy, or came in a different language set, or something like that.

went back over the code and seems I had a bad " in jason’s suggestion I was having an issue with assigning to a parameter so that is fixed.
this is the code have now and it seems to work down to last line which is the line to download the file and it is not outputting a downloaded file. this maybe the same issue as using the bigfix download as command maybe you can’t pass a parameter to a download program like curl?

wait cmd /C "curl -L “https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117” --output “C:\temp\DownloadODT\redirect.txt”“
parameter “SourceDownloadString”=”{(it, following text of last “/” of it | it) of node value of attributes “href” of xpaths (“xmlns:xhtml=‘http://www.w3.org/1999/xhtml’”, “//xhtml:a[@class=‘mscom-link failoverLink’]” ) of xml document of file “C:\temp\DownloadODT\redirect.txt”}“
parameter “SourceDownload”=”{preceding text of first ", " of parameter “SourceDownloadString”}"
wait cmd /C curl parameter “SourceDownload” --output “C:\temp\ODTdownload.exe”

if I add guards on the last line like this then it complains about needing guards

wait cmd /C "curl -L “https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117” --output “C:\temp\DownloadODT\redirect.txt”“
parameter “SourceDownloadString”=”{(it, following text of last “/” of it | it) of node value of attributes “href” of xpaths (“xmlns:xhtml=‘http://www.w3.org/1999/xhtml’”, “//xhtml:a[@class=‘mscom-link failoverLink’]” ) of xml document of file “C:\temp\DownloadODT\redirect.txt”}“
parameter “SourceDownload”=”{preceding text of first ", " of parameter “SourceDownloadString”}"
wait cmd /C curl “{parameter “SourceDownload”}” --output “C:\temp\ODTdownload.exe”

I’m not sure where you’re finding the original fixlet - can you give the Site Name and Fixlet ID? I couldn’t find it to copy Relevance from it.

In any case, I’ve tested the following Action Script in the Fixlet Debugger and it appears to be working fine. I think you may be getting a copy/paste error dealing with Smart Quotes from the Forum or wherever you’re pasting it, so you may need to delete and replace all the doublequotes

// Download the HTML page describing the download link
wait curl.exe -L "https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117" --output "__Download\test.html"

// Parse the downloaded HTML to find the download link and resulting filename for the binary installer
parameter "DownloadInfoHTML"="{(it, following text of last "/" of it | it) of node values of attributes "href" of xpaths ("xmlns:mscom='http://schemas.microsoft.com/CMSvNext'  xmlns:xhtml='http://www.w3.org/1999/xhtml'", "//xhtml:a[@class='mscom-link failoverLink']" ) of xml documents of files "__Download\test.html"}"

parameter "DownloadURL"="{tuple string item 0 of parameter "DownloadInfoHTML"}"
parameter "DownloadFile"="{tuple string item 1 of parameter "DownloadInfoHTML"}"

// Download the binary installer
wait curl -L "{parameter "DownloadURL"}" --output "__Download\{parameter "DownloadFile"}"

// Execute the binary installer (may also need CurrentUser context)
override wait
hidden=false
wait "__Download\{parameter "DownloadFile"}"

(If you have the command-line parameters for the installer, you should be able to make the installer silent as well, I don’t know whether you wanted it silent or interactive since you’re talking about using this for self-service app)

(edit: I just also tested a version that uses the plurals for “xml documents of files” and replaced it here. That could help with an edge-case where the relevance substitutions are evaluated before the action execution begins, and might throw an error parsing the files that don’t exist yet)

1 Like

That is really odd, HCL’s original one is now gone. maybe they pulled it? the name was "Install Office 365 Using ODT"
I made a copy of it this is the copy I made.

action parameter query “Channel” with description “Enter the Channel to be Installed.%0d%0aAccepted values: Current, SemiAnnual, SemiAnnualPreview, MonthlyEnterprise” with default “”

parameter “SourceFolder”="{pathname of parent folder of regapp “besclient.exe” as string & “\Office365AdvPatch”}"

if {exists folder (parameter “SourceFolder”)}
folder delete "{parameter “SourceFolder”}"
endif

folder create “{parameter “SourceFolder”}”

//downloading ODT
prefetch officedeploymenttool_13628-20476.exe sha1:43e5b0a53d23264f3931d26ad15ad0ce81bbfb8b size:3457432 https://download.microsoft.com/download/2/7/A/27AF1BE6-DD20-4CB4-B154-EBAB8A7D4A7E/officedeploymenttool_13628-20476.exe sha256:4dc80b322c4274f76e0300fd8a83afb4a9c34c8378e025dfc13dc3544b27787d

//Extracting ODT
waithidden __Download\officedeploymenttool_13628-20476.exe /quiet /extract:"{pathname of client folder of current site & “__Download”}"

move “__Download\setup.exe” “{parameter “SourceFolder”}\setup.exe”

delete __Download\configuration-Office365-x64.xml
delete __Download\configuration-Office365-x86.xml
delete __Download\configuration-Office2019Enterprise.xml
delete __Download\officedeploymenttool_13628-20476.exe

//Xml attributes
if{x32 of operating system}
parameter “Edition” = "32"
else
parameter “Edition” = "64"
endif

delete __appendfile

appendfile
appendfile <Add OfficeClientEdition="{parameter “Edition”}" Channel="{parameter “Channel”}">
appendfile
appendfile
appendfile
appendfile
appendfile
appendfile
appendfile <Updates Enabled=“TRUE” Channel="{parameter “Channel”}" />
appendfile

move __appendfile “{parameter “SourceFolder”}\configuration.xml”

waithidden “{parameter “SourceFolder”}\setup.exe” /configure “{parameter “SourceFolder”}\configuration.xml”

pause while {not exists keys whose (value “DisplayName” of it as string as lowercase contains “365”) of key “HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” of native registry}

// After installation Cleanup
folder delete "{parameter “SourceFolder”}"
Success Criteria
This action will be considered successful when the applicability relevance evaluates to false.

Link2
Script Type URL

Jason thank you very much and the last code you sent looks like it will work perfectly I tested it on the debugger and it seemed to work fine and I am testing with bigfix now and will post the full code from the fixlet as soon as I confirms it is all working.

1 Like

This below code is the finished code and it works perfectly!!! :slight_smile:
Thank you all very much for all your help on this!! sorry for the mistakes that I made that dragged out this project longer then it should have been.
Thank you all again, hope this code helps someone else.
The next project after this, is based on this idea, but prompts for a specific office version, instead of a channel. This would be useful for our customer support, that need a specific office version installed, to match the office version our customers is using, so they can reproduce an issue the customer is having.

action parameter query "Channel" with description "Enter the Channel to be Installed.%0d%0aAccepted values: Current, SemiAnnual, SemiAnnualPreview, MonthlyEnterprise" with default "<Enter the Channel Name>"

parameter "SourceFolder"="{pathname of parent folder of regapp "besclient.exe" as string & "\Office365AdvPatch"}"

if {exists folder (parameter "SourceFolder")}
	folder delete "{parameter "SourceFolder"}"
endif

folder create "{parameter "SourceFolder"}"

//downloading ODT
delete delete __createfile
wait curl.exe -L "https://www.microsoft.com/en-us/download/confirmation.aspx?id=49117" --output "__Download\test.html"
parameter "DownloadInfoHTML"="{(it, following text of last "/" of it | it) of node values of attributes "href" of xpaths ("xmlns:mscom='http://schemas.microsoft.com/CMSvNext'  xmlns:xhtml='http://www.w3.org/1999/xhtml'", "//xhtml:a[@class='mscom-link failoverLink']" ) of xml documents of files "__Download\test.html"}"
parameter "DownloadURL"="{tuple string item 0 of parameter "DownloadInfoHTML"}"
parameter "DownloadFile"="{tuple string item 1 of parameter "DownloadInfoHTML"}"
wait curl -L "{parameter "DownloadURL"}" --output "__Download\{parameter "DownloadFile"}"

//Extracting ODT
waithidden __Download\{parameter "DownloadFile"} /quiet /extract:"{pathname of client folder of current site & "\__Download"}"

move "__Download\setup.exe" "{parameter "SourceFolder"}\setup.exe"

delete __Download\configuration-Office365-x64.xml
delete __Download\configuration-Office365-x86.xml
delete __Download\configuration-Office2019Enterprise.xml
delete __Download\{parameter "DownloadFile"}

//Xml attributes
if{x32 of operating system}
parameter "Edition" = "32"
else
parameter "Edition" = "64"
endif

delete __appendfile

appendfile <Configuration>
appendfile   <Add OfficeClientEdition="{parameter "Edition"}" Channel="{parameter "Channel"}">
appendfile     <Product ID="O365ProPlusRetail" >
appendfile       <Language ID="en-us" />
appendfile     </Product>
appendfile   </Add>
appendfile <Display Level="None" AcceptEULA="TRUE" />
appendfile <Property Name="AUTOACTIVATE" Value="1" />
appendfile <Updates Enabled="TRUE" Channel="{parameter "Channel"}" />
appendfile </Configuration>

move __appendfile "{parameter "SourceFolder"}\configuration.xml"

waithidden "{parameter "SourceFolder"}\setup.exe" /configure "{parameter "SourceFolder"}\configuration.xml"

pause while {not exists keys whose (value "DisplayName" of it as string as lowercase contains "365") of key "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" of native registry}

// After installation Cleanup
folder delete "{parameter "SourceFolder"}"
1 Like

if you want an additional feature…:wink:
in conjunction with this fixlet code above, if you also want to allow the users to have the ability to select what language office they prefer to have installed, if you create a VB.net form project and add a combobox and a button to the main form. use the below code and compile it to a .exe.
create a OfficeLanguageList.csv file and place the language names in the first column and place the matching language ID codes in the second column. you can get language names and ID codes from this page. https://docs.microsoft.com/en-us/deployoffice/office2016/language-identifiers-and-optionstate-id-values-in-office-2016

Create a bigfix package upload the .exe .and the OfficeLanguageList.csv file to your package and create a “run as current user” fixlet using the .exe as the program it will run.
Add the above office fixlet code to the fixlet placing the bigfix default added line “wait run.bat” just above the line “setup.exe /configure configuration.xml” (mind you the “action parameter query” line must move up to the top to come directly after the default prefetch code.)
so that the language selector .exe runs as current user just after the appendfile’s create the configuration.xml and before the setup.exe runs the office install to use the configuration.xml.
the language selector does a find and replace on the configuration.xml using what the user selects.
language selector vb.net code below.

    Imports Microsoft.Win32
    Imports System.Diagnostics
    Imports System.IO
    Public Class Form1
        Public LanguageCode As String
        Public LanguageInfo As String
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim LanguageList As String = ".\OfficeLanguageList.csv"
            Try
                If File.Exists(LanguageList) Then
                    Using sr As New StreamReader(LanguageList)
                        While Not sr.EndOfStream
                            Dim lineText As String() = sr.ReadLine().Split(";"c)
                            ComboBox1.Items.Add(lineText.Last)
                            LanguageCode = "en-us"
                        End While
                    End Using
                End If
            Catch ex As Exception
            End Try
        End Sub

        Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Try
                    My.Computer.FileSystem.WriteAllText(".\configuration.xml", My.Computer.FileSystem.ReadAllText(".\configuration.xml").Replace("en-us", LanguageCode), False)
                Catch ex As Exception
                End Try
            Close()
        End Sub

        Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
            LanguageInfo = ComboBox1.GetItemText(ComboBox1.SelectedItem)
            LanguageCode = LanguageInfo.Substring(LanguageInfo.LastIndexOf(",") + 1)
        End Sub
    End Class