ブログBLOG

2017年1月の記事

Nintex Worflowで、PowerShell実行ってできるの?

2017年01月13日(金)

皆様こんにちは、インフォシェアの小高です。

少し時間が空いてしまいましたが、Nintexの連載記事Season2です。

今回はPowerShell実行について考えてみたいと思います。
この内容、結構話にでることも多く、ご興味のある方もいるかと思います。

実際に確認してみると、Nintex標準ではできなかったものの、やりようによって出来ることはわかりましたので一瞬夢が広がったわけですが、すぐに現実に引き戻されるという結果になりました(汗)

連載記事(Season2)の目次はこちらから。
連載記事(Season1)の目次はこちらからになります。

———————

今回も最初にお話ししてしまうと、Nintex Workflowの標準機能としてはPowerShellを実行するようなアクションは存在しません。

ですがCodePlexに行くと、Nintex関係のプロジェクトもいくつか存在しています。
その中の一つ、例えばこちらは ⇒ https://ntx.codeplex.com/ 、PowerShellの実行用のNintexWFのアクションとなります。
(注意)CodePlexは、有志が作成したオープンソースプロジェクトですので、Nintex社や弊社のサポートが受けられるわけではありません。試される際は、あくまでも自己責任でお願いいたします。

ダウンロードすると、以下のようなファイルがありますので、wspをps1を用いてSharePoint環境にインストールしていきます。この辺りは、上記のページやps1を確認の上慎重に行う必要があります。

image_thumb.png

WFの中で使用するには、全体管理-「Nintexの管理」-「Workflow環境」-「アクションの設定」にてチェックをいれる必要があります。私の環境では何故か下図のように3つ出てくるのですが、中を見ると全て同じパブリックキートークンを持つアセンブリを指しているので、1つだけチェックしてみました。(これで動作しています。)

image

そうすると、WFのデザイナに下図のようなアクションが表示されます。

image_thumb-2

設定は下図のような感じになります。

image

注意頂きたいのは、PowerShellをどのサーバーで実行するか?という点です。この点に関しては、私もかなり試行錯誤しましたが、要するにPowerShellのリモート実行を実現しなくてはならないわけです。さすがに適当なことは書けませんので、以下辺りを参考にして環境を構築しましたという付帯情報だけお伝えしておきます。

Windows PowerShell: 次ホップを実行する
Enable PowerShell "Second-Hop" Functionality with CredSSP
Enabling Multihop Remoting

今回試しに実行してみたのは以下のPowerShellスクリプトになります。サイトの権限一覧をCSVに出力して、ライブラリにアップする感じです。(本当はリストやアイテムもあると良いのですが簡易版ということで。)

$snapInInfo = Get-PSSnapin | Where-Object{$_.Name -eq "Microsoft.SharePoint.PowerShell"}

if($snapInInfo -eq $null)
{
Add-PSSnapin Microsoft.SharePoint.PowerShell
}

# サイトコレクション一覧を取得
$siteCollections = Get-SPSite

"{0},{1},{2},{3},{4},{5},{6},{7},{8}" -f "サイト:URL", "サイト:タイトル","リスト/ライブラリ:URL", "リスト/ライブラリ:タイトル","ユーザー/グループ:LoginName", "ユーザー/グループ:Name", "ロール","グループ:LoginName","グループ:Name"|Add-Content "c:tempUserInfo.csv"

# サイトコレクション分だけ繰り返す
ForEach($siteCollection in $siteCollections)
{
# サイトコレクション配下にあるサブサイトを取得する
$sites = Get-SPWeb -Site $siteCollection.Url

# サブサイト分だけ繰り返す
ForEach($site in $sites)
{
#■サイトの実行
#継承をしていないサイトのみを対象にする
IF($site.HasUniqueRoleAssignments)
{
#サイトのパーミッション(ユーザー/グループ)分だけ繰り返す
ForEach($Permission in $site.RoleAssignments)
{
$RoleName = ""
#パーミッション(ユーザー/グループ)のロールの数分だけ繰り返す
ForEach($Role in $Permission.RoleDefinitionBindings)
{
$RoleName += $Role.Name + " "
}
"{0},{1},{2},{3},{4},{5},{6},{7},{8}" -f $site.Url, $site.Title,"","",$Permission.Member.LoginName, $Permission.Member.Name, $RoleName,"",""|Add-Content "c:tempUserInfo.csv"
#パーミッション(グループ)にメンバーが所属している場合情報を出力する
IF($Permission.Member.Users.Count -gt 0 )
{
#パーミッション(グループ)のメンバー分だけ繰り返す
ForEach($User in $Permission.Member.Users)
{
"{0},{1},{2},{3},{4},{5},{6},{7},{8}"  -f $site.Url, $site.Title,"","",$User.LoginName, $User.Name, "",$Permission.Member.LoginName, $Permission.Member.Name|Add-Content "c:tempUserInfo.csv"
}
}
}
}
}
}

$WebURL = "サーバー名"
$DocLibName = "Shared%20Documents"
$FilePath = "C:tempUserInfo.csv"
$Web = Get-SPWeb $WebURL
$List = $Web.GetFolder($DocLibName)
$Files = $List.Files
$FileName = $FilePath.Substring($FilePath.LastIndexOf("") +1)
$FilePath
$File= Get-ChildItem $FilePath
# Upload it to SharePoint
$Files.Add($DocLibName + "/" + $FileName,$File.OpenRead(), $false)
$web.Dispose()

こちらを上記の設定(PowerShell Script)に直接記載してもよいですし、下図のようにシェアにps1ファイルおいて実行も可能でした。

image

作成したフローは非常に単純でして、上記を実行した後、結果(Result Output)を列に更新するようにしています。(どうやら結果はShellに出力した値がResult Outputにて取得できるようです。)

image

実行結果としては以下のようになっています。

image

作成したCSVファイルもアップされてますね。

image

ちなみにCSVの中身はこんな感じになってます。image

と言うわけで、PowerShellの実行が可能になったわけです。
これ、良く考えるとすごい可能性を秘めていると思うんですよ。

例えば、今回の例でも、
・SharePointファーム内の全ての権限情報をCSVにする
・定期的に実行する(スケジュール実行)
・ファイル名が重ならないような考慮
など、上記に少しの工夫をいれるだけで、簡単な管理ソリューションが実現できてしまいそうです。夢が広がりまくりんぐですねー

ただですね、ここ非常に重要なポイントですが、PowerShell、やろうと思えばなんでもできちゃいますので、設計や実行にはかなり注意しなければなりません。(極端な話.NETのプログラムも書けてしまいます。ドキュメントジェネレーションのソリューションも出来ちゃうんじゃなかろうか、、、

また、SharePointファームの構成や、PowerShellをどのサーバーで実行するかなどの環境に関しても、非常にセンシティブな問題となりますから、その辺りも注意した方が良いです。

それと再度記載しますが、CodePlexがベースになっていますので、あくまでも自己責任になる件もお忘れなき様にしてくださいね。

あぁ夢から現実に戻ってきてしまった・・・

それではまた。