My Tool: Using Gulp and Powershell to Automate File Uploading and Approval for SharePoint 2010
Usges
Automate uploading all changed files to SharePoint
c:\dev\wan\MyProject\gulp defaultor
c:\dev\wan\MyProject\gulp spdefault
Automate appoving all files in SharePoint
c:\dev\wan\MyProject\gulp approveallAutomate checking in all files in SharePoint
c:\dev\wan\MyProject\gulp checkinallAutomate checking out all files in SharePoint
c:\dev\wan\MyProject\gulp checkoutallNote
- Please ensure Powershell version must be at least 4 ! ($PSVersionTable.PSVersion)
- To Map Network Drive, WebDAV must be installed (Server Feature/Desktop Experience/Restart Server, enable WebClient service)
- if the mapped drive Z: is not recognized in powershell or command line, please "net use Z: http://pre.dev.com" instead
- Please login to Z: first else copying will fail due to no access
Content of c:/dev/wan/MyProject/gulpfile.js
// https://www.spdavid.com/use-gulp-and-npm-to-automate-2/
// For SP2013 and SP 2016: https://www.definitivelogic.com/2017/02/21/legacy-sharepoint-gulp-robocopy/
// For SP2010: https://www.definitivelogic.com/2017/02/28/legacy-sharepoint-development-2007-and-2010-gulp-and-robocopy/
// http://thomasdaly.net/2018/01/05/sharepoint-quick-deploy-build-process-using-node-gulp-sp-save-part-2/
var gulp = require('gulp')
var spsave = require('gulp-spsave')
var watch = require('gulp-watch')
var cached = require('gulp-cached');
var robocopy = require('robocopy');
var powershell = require('node-powershell');
var sourceDir = "c:/dev/wan/MyProject";
var mapDrive = "Z:";
var rootSiteUrl = "http://pre.dev.com";
var filelist = [
{
files: ["EServices.txt"], // source files, separated by ","
subSiteUrl: "", // destination subsite url ("" means root site)
folder: "/Pages", // destination folder within this subsite (related to subSiteUrl)
copy: true // true (default): copy these files; false: don't copy
},
{
files: ["EServices.js"],
subSiteUrl: "",
folder: "/Pages/EServices/js",
copy: true
},
{
files: ["jquery.smartWizard.fix.js"],
subSiteUrl: "",
folder: "/Pages/EServices/js",
copy: true
}, {
files: ["jquery.smartWizard.custom.js"],
subSiteUrl: "",
folder: "/Pages/EServices/js",
copy: true
},
{
files: ["smart_wizard_theme_dots_custom.css"],
subSiteUrl: "",
folder: "/Pages/EServices/css",
copy: true
},
{
files: ["EServices.css"],
subSiteUrl: "",
folder: "/Pages/EServices/css",
copy: true
},
{
files: ["Licence.txt"],
subSiteUrl: "",
folder: "/Pages/EServices",
copy: true
},
{
files: ["Application.txt"],
subSiteUrl: "/Applications",
folder: "/Pages",
copy: true
},
{
files: ["Subsidy.txt", "Calculator.txt"],
subSiteUrl: "/Services/Subsidy",
folder: "/Pages",
copy: true
}
];
function copyall(filelist) {
// files must be checked out before being overwritten
spfileversioningall(filelist, "CheckOut");
for (var i=0; i< filelist.length; i++) {
if (typeof filelist[i].copy == typeof udnefined || filelist[i].copy) {
robocopy({
source: sourceDir,
destination: mapDrive + filelist[i].subSiteUrl + filelist[i].folder,
files: filelist[i].files,
copy: {
info: 'DT'
},
retry: {
count: 1,
wait: 3
}
})
}
}
}
function spfileversioningall(filelist, func) {
for (var i=0; i< filelist.length; i++) {
if (typeof filelist[i].copy == typeof udnefined || filelist[i].copy) {
for (var j=0; j < filelist[i].files.length; j++) {
spfileversioning(func, rootSiteUrl + filelist[i].subSiteUrl, filelist[i].subSiteUrl + filelist[i].folder + "/" + filelist[i].files[j]);
}
}
}
}
function spfileversioning(func, siteUrl, fileServerRelativeUrl) {
let ps = new powershell({
executionPolicy: 'Bypass',
noProfile: true
});
ps.addCommand('./SPFileVersioning.ps1', [
{"function": func},
{"siteUrl": siteUrl},
{"fileServerRelativeUrl": fileServerRelativeUrl}
])
ps.invoke()
.then(output => {
console.log(output);
ps.dispose();
})
.catch(err => {
console.log(err);
ps.dispose();
});
}
gulp.task('spdefault', function() {
// runs the spsave gulp command on only files the have
// changed in the cached files
return gulp.src(sourceDir + "/*")
.pipe(cached('spFiles'))
.pipe(copyall(filelist));
});
gulp.task('default', function() {
// create an initial in-memory cache of files
gulp.src(sourceDir + "/*")
.pipe(cached('spFiles'));
// watch the src folder for any changes of the files
gulp.watch([sourceDir + "/*"], ['spdefault']);
});
gulp.task('approveall', function() {
spfileversioningall(filelist, "approve");
});
gulp.task('checkinall', function() {
spfileversioningall(filelist, "checkin");
});
gulp.task('checkoutall', function() {
spfileversioningall(filelist, "checkout");
});
Content of c:/dev/wan/MyProject/SPFileVersioning.ps1
<#
https://bramdejager.wordpress.com/2013/08/02/using-csom-and-powershell-to-query-sharepoint-online-or-on-premise/
https://stackoverflow.com/questions/36585936/sharepoint-csom-powershell-does-not-return-web-folders-property/36671910
http://www.sharepointdiary.com/2016/10/sharepoint-online-how-to-check-in-document-using-powershell.html
https://wprogramming.wordpress.com/2011/07/18/dynamic-function-and-variable-access-in-powershell/
https://social.technet.microsoft.com/wiki/contents/articles/26436.how-to-create-and-use-enums-in-powershell.aspx
#>
param(
[string] $function = "approve",
[string] $siteUrl = "http://pre.dev.com",
[string] $fileServerRelativeUrl = "/Pages/EServices/js/jquery.smartWizard.fix.js"
)
#Add-PSSnapin Microsoft.SharePoint.Powershell #-ErrorAction SilentlyContinue
#We will use CSOM to access SharePoint folders
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\SharePoint Client\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\SharePoint Client\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -TypeDefinition @"
public enum SPModerationStatusType
{
Approved,
Denied,
Pending,
Draft,
Scheduled
}
"@
Function CheckIn($siteUrl, $fileServerRelativeUrl)
{
<#
To check in a file in root site:
.\SPFileVersioning.ps1 -function CheckIn -siteUrl "http://pre.dev.com" -fileServerRelativeUrl /Pages/EServices/js/Test.html
To check in a file in a sub site:
./SPFileVersioning.ps1 -function CheckIn -siteUrl http://pre.dev.com/Services/Subsidy -fileServerRelativeUrl /Services/Subsidy/Calculator.txt
#>
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
Try {
$file = $ctx.Web.GetFileByServerRelativeUrl($fileServerRelativeUrl)
$ctx.Load($file)
$ctx.ExecuteQuery()
If($file.CheckOutType -eq "None")
{
write-host "$($file.Name) is not checked out and no need to be checked in!" -f Red
}
else
{
# MajorCheckIn is equivalent to Publish("")
$file.CheckIn("",[Microsoft.SharePoint.Client.CheckinType]::MajorCheckIn)
$ctx.ExecuteQuery()
write-host "$($file.Name) has been checked-in successfully!" -f Green
}
}
Catch {
write-host -f Red "Error checking-in $($file.Name)!" $_.Exception.Message
}
}
Function CheckOut($siteUrl, $fileServerRelativeUrl)
{
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
Try {
$file = $ctx.Web.GetFileByServerRelativeUrl($fileServerRelativeUrl)
$ctx.Load($file)
$ctx.ExecuteQuery()
#check if the file is already checked out
If($file.CheckOutType -ne "None")
{
write-host "$($file.Name) is already checked out!" -f Yellow
}
else
{
$file.CheckOut()
$ctx.ExecuteQuery()
write-host "$($file.Name) has been checked out successfully!" -f Green
}
}
Catch {
write-host -f Red "Error checking out $($file.Name)!" + $_.Exception.Message
}
}
Function Approve($siteUrl, $fileServerRelativeUrl)
{
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
Try {
$file = $ctx.web.GetFileByServerRelativeUrl($fileServerRelativeUrl)
$item = $file.ListItemAllFields
$ctx.Load($file)
$ctx.Load($item)
$ctx.ExecuteQuery()
# CSOM ListItem class does not have a ModerationInformation property!
if( $item["_ModerationStatus"] -eq [SPModerationStatusType]::Approved) {
write-host "$($file.Name) is already approved and no need to be re-approved" -f Green
}
else
{
if( $item["_ModerationStatus"] -eq [SPModerationStatusType]::Draft) {
CheckIn -siteUrl $siteUrl -fileServerRelativeUrl $fileServerRelativeUrl
}
# must re-read $item to prevent error:"Version conflict."
$ctx.Load($item)
$ctx.ExecuteQuery()
$item["_ModerationStatus"] = [Convert]::ToInt32([SPModerationStatusType]::Approved);
$item.Update();
$ctx.ExecuteQuery()
write-host "$($file.Name) has been approved successfully!" -f Green
}
}
Catch {
write-host -f Red "Error approving $($file.Name)!" + $_.Exception.Message
}
}
& $function -siteUrl $siteUrl -fileServerRelativeUrl $fileServerRelativeUrl
Comments
Post a Comment