Content Type Publishing Settings

The SharePoint client object model (CSOM) can do a lot of things.  But, there are also a lot of things that are not (yet) supported. I recently ran into one of these gaps while attempting to publish content types with PowerShell in SharePoint Online. I wanted to be able to create a new content type in the content type hub and publish it out to other site collections from a single script.

I often use PowerShell to automate the activity of the browser as a COM object to accomplish things where there is not any API support, but it is something that you can do in the browser.  This simulates opening the browser, browsing to the desired settings page, making your changes, and clicking OK.  The main difference is that instead of me performing the actions, a PowerShell script is doing all of the work.

The PowerShell function below will publish a content type for distribution to all site collections in your tenant.

UPDATE 7/13/206: Make sure that you run the script as an Administrator.  If you do not, you may receive the following error: The object invoked has disconnected from its clients. (Exception from HRESULT: 0x80010108 (RPC_E_DISCONNECTED))

function Publish-ContentType {
param(
[Parameter(Mandatory = $true)] [string]$ContentTypeHubUrl,
[Parameter(Mandatory = $true)] [string]$ContentTypeId,
[Parameter(Mandatory = $true)] [string]$Username,
[Parameter(Mandatory = $true)] [string]$Password
)

Write-Host "Logging into SharePoint via the browser"

# create a new COM object for IE autmation
$ie = New-Object -ComObject 'internetExplorer.Application'
$ie.Visible = $true

# if a user is logged in, log them out
$ie.Navigate("https://login.microsoftonline.com/logout.srf")
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 400 }

#navigate to the Office 365 login page
$ie.Navigate("https://login.microsoftonline.com/login.srf")
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 400 }

# get the page elements. GetElementById will not work in modern operating systems. Use the workaround as shown
$usernameField = $ie.Document.body.getElementsByTagName('input') |? {$_.id -eq 'cred_userid_inputtext' }
$passwordField = $ie.Document.body.getElementsByTagName('input') |? {$_.id -eq 'cred_password_inputtext' }
$signInButton = $ie.Document.body.getElementsByTagName('button') |? {$_.id -eq 'cred_sign_in_button' }

# simulate the same actions the user would perform while logging in
$usernameField.focus()
$usernameField.value = $Username
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 400 }
$passwordField.focus()
$passwordField.value = $Password

# to get the login to work, first set focus and click on the sign in button. Then, wait for
# the username postback to complete and click the button again
$signInButton.focus()
$signInButton.click()
Start-Sleep -Seconds 3
$signInButton.click()
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 400 }

# navigate to the publishing settings page for the content type
Write-Host "Publishing content type"
$ie.Navigate("$($ContentTypeHubUrl)/_layouts/15/managectpublishing.aspx?ctype=$($ContentTypeId)")
Start-Sleep -Seconds 3
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 400 }

# throw an error if we do not reach the content type publishing page (i.e. failed login, bad content type id)
if (-not $ie.Document.location.pathname.EndsWith("/_layouts/15/managectpublishing.aspx")) {
throw "Unable to navigate to content type publishing page."
}

$publishButton = $ie.Document.body.getElementsByTagName('input') |? {$_.value -eq 'publishButton' }
$publishButton.checked = $true
$okButton = $ie.Document.body.getElementsByTagName('input') |? {$_.value -eq 'OK' }
$okButton.click()
while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 400 }

$ie.Quit()
}
Share
This

2 Comments

  1. Kill says:

    I’ll right away grab your rss feed as I can not to find your e-mail subscription hyperlink or newsletter service.
    Do you’ve any? Please let me realize in order that I could
    subscribe. Thanks.

    1. Travis Lingenfelder says:

      Thanks for your interest. You can register for our news letter at the bottom of the page. You can also engage with us using the social media links at both the top and bottom of the page.

Post a comment