からめもぶろぐ。

俺たちは雰囲気で OAuth をやっている

削除できなくなった SharePoint 2013 ワークフローを強制的に削除する

SharePoint Designer で SharePoint 2013 ワークフローを開発しているとまれに作成したワークフローを削除できなくなることがあります。具体的には、再利用可能なワークフローを作成し、テンプレートとして保存し、保存したテンプレートから展開した場合に、ワークフローが削除できなくなることが確認できています。この場合、SharePoint Designer で削除できないだけでなく、CSOM から WorkflowDeploymentService.DeleteDefinition メソッドを呼び出しても削除できません。
削除できないと最悪サイトの作り直しになってしまいますので、頑張って無理やり削除してみたいと思います。

まず、SharePoint 2013 ワークフローの情報はどこに格納されているかというと「wfsvc」という隠しドキュメントライブラリにあります。「wfsvc」は GUI からも SharePoint Designer からも見えませんが、CSOM からであれば確認することができます。

試しに SharePoint Designer で SharePoint 2013 ワークフローを作成してみます。

CSOM でワークフローが存在することを確認します。

Add-Type -LiteralPath "$PSScriptRoot\Microsoft.SharePoint.Client.dll"
Add-Type -LiteralPath "$PSScriptRoot\Microsoft.SharePoint.Client.Runtime.dll"

$siteurl = "{{siteurl}}"
$username = "{{username}}"
$password = "{{password}}"

$password = ConvertTo-SecureString $password -AsPlainText -Force
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
$context = New-Object Microsoft.SharePoint.Client.ClientContext($siteurl)
$context.Credentials = $credentials

$web = $context.Web
$context.Load($web)
$context.ExecuteQuery()

$list = $web.GetList($web.ServerRelativeUrl.TrimEnd('/') + '/wfsvc')
$query = New-Object Microsoft.SharePoint.Client.CamlQuery
$query.ViewXml = '<View Scope="RecursiveAll"></View>'
$items = $list.GetItems($query)
$context.Load($items)
$context.ExecuteQuery()

foreach ($item in $items) {
    Write-Output ([pscustomobject]@{ Path = $item['FileRef']; Name =  $item['WSDisplayName'] })
}

実行すると以下のような結果が返ってきます。

Path                                                  Name
----                                                  ----
/wfsvc/a1ef7b8ae5554ee18af83707d4bdef88
/wfsvc/a1ef7b8ae5554ee18af83707d4bdef88/workflow.xaml Test Workflow 1

workflow.xaml がワークフローの本体です。よってこれをフォルダーごと削除してしまいます。

$folder = $web.GetFolderByServerRelativeUrl('/wfsvc/a1ef7b8ae5554ee18af83707d4bdef88')
$folder.DeleteObject()
$context.ExecuteQuery()

削除されました!