How to create a sharepoint site collection remotely via powershell? - powershell

How to create a new site collection remotely via Powershell
I have tried the following and all failed
Trial one:
# Create a PSCredential Object using the "User" and "Password" parameters that you passed to the job
$SecurePassword = '...............' | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList "domain\user", $SecurePassword
$spms = New-PSSession -ComputerName servername -Credential $cred
$Parameters= #{
Session = $spms
ArgumentList ="siteurl","sitename",'domain\user','domain\user2'
ScriptBlock = { Param ($SiteURL,$SiteName,$SiteOwner,$SecondSiteOwner)
Add-PSSnapin Microsoft.sharepoint.powershell -ErrorAction SilentlyContinue
Function Recreate_Site_Collection ($SiteURL,$SiteName,$SiteTemplate,$SiteOwner,$SecondSiteOwner){
# Delete Site Collection
$site = get-spsite -Identity $SiteURL -ErrorAction SilentlyContinue
if($site){
Write-host "Removing the site $SiteURL" -f Red
Remove-SPSite -Identity $SiteURL -Confirm:$false
}
# Create Site Collection
Write-host "creating the site $SiteURL" -f green
echo $SiteOwner
echo $SecondSiteOwner
New-SPSite -Name $SiteName -Url $SiteURL -Template $SiteTemplate -OwnerAlias $SiteOwner -SecondaryOwnerAlias $SecondSiteOwner -Confirm:$false
}
$SiteTemplate = "DEV#0" #Developer Site Template
Recreate_Site_Collection $SiteURL $SiteName $SiteTemplate $SiteOwner $SecondSiteOwner
}}
Invoke-Command #Parameters
Error:
The user cannot be found.
however, if I run the same code on the server with the same variables it goes ok when I run the PowerShell as an admin
Trial two:
# Create a PSCredential Object using the "User" and "Password" parameters that you passed to the job
$SecurePassword = '..........' | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList "domain/user", $SecurePassword
$spms = New-PSSession -ComputerName servername -Credential $cred
$Parameters= #{
Session = $spms
ArgumentList = "siteurl","sitename",'domain/user',"1033","DEV#0"
ScriptBlock = { Param ($PortalUrl,$SiteName,$userName,$LCID,$WebTemplate)
$adminSiteUrl = "centraladminurl"
$user = "user"
$pwd = '..............'
$securePwd = ConvertTo-SecureString $pwd -AsPlainText -Force
$cred = New-Object PSCredential($user, $securePwd)
$wsdlUrl = $adminSiteUrl + "/_vti_adm/Admin.asmx?WSDL"
$svc = New-WebServiceProxy -Uri $wsdlUrl -Credential $cred
$svc.Timeout = 300000 # 5 minute timeout
$svc.CreateSite(
$siteUrl, # URL
$siteTitle, # Title
$Description, # Description
$LCID, # LCID 1033 arabic
$WebTemplate, # WebTemplate
$user, # Owner Login
"user", # Owner Name
"mail",
$PortalUrl ,
"portalname"
)}}
Invoke-Command #Parameters
Error:
Exception calling "CreateSite" with "10" argument(s): "Exception of type 'Microsoft.SharePoint.SoapServer.SoapServerException' was thrown."
however, also when running the same script on the server itself with PowerShell run as admin it works with the same variables
please help
I need to automate SharePoint deployment from Jenkins which require a remotely PowerShell script and the main step is creating the site it cannot be established

It's definitely a permissions issue, but it can be kind of a pain to find. My user (the one running the script - probably your Jenkins user) was:
a local admin on the server,
listed in https://sharepointsite/ > Site Settings > Permissions > Site Collection Administrators.
but still got weird errors when running remotely:
# These commands did not work - I'm quoting the errors:
Enter-PSSession -ComputerName MySPServer
Add-PSSnapIn Microsoft.SharePoint.PowerShell
$URI = 'https://MySharePoint.domain.com'
# Can't pipe Site object to Web
Get-SPSite $URI | Get-SPWeb
'Get-SPWeb : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))'
# Can't get SP users using web:
$web = Get-SPWeb $URI
Get-SPUser 'DOMAIN\user' -Web $web
'Get-SPUser : Cannot find an SPWeb object with Id or Url: 7aee0dc1-fe3b-4f9b-bd4b-000000000000 and Site Id: 8b662499-bb26-41ce-978e-000000000000.'
# Can't list properties of a site object
Get-SPSite $URI | fl
'Exception has been thrown by the target of an invocation.'
# Can't create a new site because the user can't be found:
New-SPSite -Url $URI -Name 'Test' -Description 'Test Site' -Template 'DEV#0' -OwnerAlias 'DOMAIN\user'
'New-SPSite : User cannot be found.'
I found that my user was not showing up as a site admin in powershell for some reason. Note that I'm running directly on the server here in order to view the users:
$URI = 'https://MySharePoint.domain.com'
$web = Get-SPWeb $uri
Get-SPUser "$env:USERDOMAIN\$env:USERNAME" -Web $web | Select UserLogin,IsSiteAdmin,IsSiteAuditor,AllowBrowseUserInfo
'UserLogin IsSiteAdmin IsSiteAuditor AllowBrowseUserInfo
--------- ----------- ------------- -------------------
DOMAIN\user False False True'
So I added myself as a site admin for my main site like so:
# Set my user as collection admin:
Get-SPUser 'DOMAIN\User' -Web $web | Set-SPUser -IsSiteCollectionAdmin:$true
# Check permissions again:
Get-SPUser "$env:USERDOMAIN\$env:USERNAME" -Web $web | Select UserLogin,IsSiteAdmin,IsSiteAuditor,AllowBrowseUserInfo
'UserLogin IsSiteAdmin IsSiteAuditor AllowBrowseUserInfo
--------- ----------- ------------- -------------------
DOMAIN\user True True True'
Get-SPSite $uri | fl UserIsSiteAdminInSystem
'UserIsSiteAdminInSystem : True'
And now all of the above commands work normally. It seems like the powershell module for sharepoint requires some access to the main webservice object in order to resolve usernames. I'm not sure what level of access is really required, but this worked for me.

Related

How to use different owner in new-pnpsite command in powershell

I use New-PNPSite from PNP Module to create a new SharePoint communication site like this
$username = "admin#gmail.com"
$secpasswd = ConvertTo-SecureString -String "password" -AsPlainText -Force
$UserCredential = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $username, $secpasswd
$Url = 'https://companyAdmin.sharepoint.com/'
Connect-PnPOnline -url $Url -Credentials $UserCredential
New-PNPSite -Type CommunicationSite -Title "Testing 2" -Owner "differentuser#gmail.com" -url "https://company.sharepoint.com/sites/jontesting2" -Lcid 1033
but I'm getting this error for some reason
New-PNPSite : {"SiteId":"","SiteStatus":3,"SiteUrl":""}
if I use the admin address admin#gmail.com in the owner parameter then I don't get the error and I'm able to create a new site. Any idea why it might be?
I wanted to use the admin account to create a new site for different owners that's why.

New-PSDrive's "-Persist" flag not working: drives removed on reboot

The script mounts the drive correctly, but the drive is not persisted after rebooting the machine:
function RemapDrive {
param(
$DriveLetter,
$FullPath,
$Credential
)
Write-Host "Trying to remove $DriveLetter in case it already exists ..."
# $DriveLetter must be concatenated with ":" for the command to work
net use "${DriveLetter}:" /del
## $DriveLetter cannot contain ":"
$psDrive = New-PSDrive -Name "$DriveLetter" -PSProvider "FileSystem" -Root "$FullPath" -Credential $Credential -Scope "Global" -Persist
Write-Host "$DriveLetter was successfully added !"
}
function BuildCredential {
param (
$Username,
$Password
)
$pass = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($Username, $pass)
return $credential
}
$credential = (BuildCredential -Username "xxxxxx" -Password "yyyyyy")[-1]
RemapDrive -DriveLetter "X" -FullPath "\\my-server\x" -Credential $credential
What I have found:
“When you scope the command locally, that is, without dot-sourcing, the Persist parameter does not persist the creation of a PSDrive beyond the scope in which you run the command. If you run New-PSDrive inside a script, and you want the new drive to persist indefinitely, you must dot-source the script. For best results, to force a new drive to persist, specify Global as the value of the Scope parameter in addition to adding Persist to your command.”
I have tried executing the script with ". .\my-script.ps1" (to dot-source the script?), but the result is the same.
Playing around with "net use" and the registry to try to add the network drive has lead me to a cul-de-sac as well.
Specs:
Windows 10 Home
Powershell version:
Major Minor Build Revision
----- ----- ----- --------
5 1 18362 1171
Basically, New-PSDrive doesn't have the /SAVECRED parameter from net use, and will not persistently map drives as a user other than the one running the script.
There are three ways to handle this:
[Recommended] Fix the file share permissions instead of using a separate username/password, then use New-PSDrive -Name "$DriveLetter" -PSProvider "FileSystem" -Root "$FullPath" -Scope 'Global' -Persist with no credential flag. This assumes your file share allows kerberos logins, so may not work in some edge cases.
Use net use, and include the username, password, /persistent:yes and /savecred. This can be done in powershell without any issues.
Set the powershell script you already have to run at startup.
Set up your script to use the credential manager - see the answer here
Install the CredentialManager powershell module
set HKCU\Network\[drive letter]\ConnectionType = 1
set HKCU\Network\[drive letter]\DeferFlags= 4
What finally work was user19702's option #2, with a bit of extra work regarding the registration of the username and the password.
WARNING: as he mentioned, the best option (option #1) would have been "fixing the file share permissions instead of using a separate username/password". This was not possible in my case, and this is why I had to go with option #2.
This is the script:
# ---
# Helper functions:
function RemapDrive {
param(
$DriveLetter,
$Server,
$FullPath,
$Credential
)
# For net.exe to work, DriveLetter must end with with ":"
Write-Host "Trying to remove $DriveLetter in case it already exists ..."
net use "$DriveLetter" /del
# "net use" requires username and password as plain text
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($credential.Password)
$Password = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
$Username=$Credential.Username
Write-Host "Registring credentials for server '$Server' ..."
cmdkey /add:$Server /user:$Username /pass:$Password
Write-Host "Mapping the drive ..."
net use $DriveLetter $FullPath /persistent:yes i
Write-Host "$DriveLetter was successfully added !"
}
function BuildCredential {
param (
$Username,
$Password
)
$pass = ConvertTo-SecureString $Password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($Username, $pass)
return $credential
}
# ---
# Process to execute:
$credential = (BuildCredential -Username "xxxxxx" -Password "yyyyyy")[-1]
RemapDrive -DriveLetter "X:" -Server "my-server" -FullPath "\\my-server\x" -Credential $credential
If you do not want to use a hardcoded password in BuildCredential, but you want to prompt the user instead:
function GetCredential {
param(
$Label
)
$credential = Get-Credential -Message "Write your credentials for '$Label':"
if(!$credential) {
throw "A credential was needed to continue. Process aborted."
}
return $credential
}
Also, if instead of using $Server as a param, you want to extract it from $FullPath using regex, you can do that.
It presumes the $FullPath has the following format: \\server-name\dir1\dir2\etc
# Get server name using regex:
$FullPath -match '\\\\(.*?)\\.*?'
$Server = $Matches[1]

SharePoint OnLine Using PowerShell PNP

I am a young SharePoint OnLine user. I want Excel documents from all my sites to open directly with Excel and not Excel-OnLine. As I have a lot of sites and it would be long to make the sites one by one, I try to made a PowerShell without success :
$tenantName = "myTenant"
$username = "my#email.com"
$password = "myPassword"
$url = "MySharePointSiteToTest"
# Reference au module Pnp Client
# En cas de problème, vérifier les chemains d'accès !
$pnpModule = Get-Module SharePointPnPPowerShell* -ListAvailable
$pnpPath = $pnpModule.ModuleBase
Add-Type -Path "C:\PSTools\Modules\SharePointPnPPowerShellOnline\2.15.1705.0\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\PSTools\Modules\SharePointPnPPowerShellOnline\2.15.1705.0\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\PSTools\Modules\SharePointPnPPowerShellOnline\2.15.1705.0\Microsoft.SharePoint.Client.UserProfiles.dll"
Add-Type -Path "C:\PSTools\Modules\SharePointPnPPowerShellOnline\2.15.1705.0\Microsoft.Online.SharePoint.Client.Tenant.dll"
# internal params
$adminUrl = "https://$tenantName-admin.sharepoint.com"
$rootUrl = "https://$tenantName.sharepoint.com"
Write-Host *********************************
Write-Host "Admin Url : $adminUrl"
Write-Host "Root Url : $rootUrl"
Write-Host *********************************
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
# Admin connection
$adminCtx = New-Object Microsoft.SharePoint.Client.ClientContext($adminUrl)
# SharePoint Online with PNP
$psCredential = New-Object System.Management.Automation.PSCredential($username, $securePassword)
$spCredential = Get-Credential -Credential $psCredential
# PnP Connect
Connect-PnPOnline -Url $url -Credentials $spCredential
#Permet d'activer la fonctionalitée de l'ID correspondant
Enable-PnPFeature -Identity 8a4b8de2-6fd8-41e9-923c-c7c3c00f8295 -Force
I don't get an error. Obviously I have to forget something in the code

PowerShell to Export SharePoint Sites and Subsides with security groups

I'm attempting to come up with a powershell script that would allow me to export a list of sites and subsites and the permission groups there in to a CSV.
I'm familiar with using the cmdlts but not building whole scripts.
I'm able to use:
Get-SPOSiteGroup | Export-CSV C:\...
To export site groups to a CSV but it doesn't include the name of the sites they are in.
I also found a script online that would print out the sites and subsite in my site collection here:
https://sharepoint.stackexchange.com/questions/101176/powershell-to-list-all-sites-and-subsites-in-sharepoint-online
I'm not sure how to marry the information. I'm trying to export to a CSV a list of sites and subsites and the security groups there in.
I try to run:
get-sposite | Get-SPOSiteGroup **webdite**
And get this error message:
"Get-SPOSiteGroup : The input object cannot be bound to any parameters
for the command either because the command does not take pipeline
input or the input and its properties do not match any of the
parameters that take pipeline input"
I'm not sure how to get all of this to work together.
Get-SPOSiteGroup cmdlet accepts Site parameter, so site groups per every site collection within a tenant could be retrieved like this:
Connect-SPOService -Url $adminUrl
$sitesInfo = Get-SPOSite
#Retrieve and print all sites
foreach ($site in $sitesInfo) {
Write-Host 'Site collection:' $site.Url
Get-SPOSiteGroup -Site $site.Url
Write-Host '-----------------------------'
}
To retrieve in addition groups per every web site, the following script could be utilized:
$adminUrl = "https://<tenant>-admin.sharepoint.com"
$UserName = "<username>#<tenant>.onmicrosoft.com"
$Password = "--password goes here--"
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
$creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName, $SecurePassword)
$pscreds = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $userName, $SecurePassword
Connect-SPOService -Url $adminUrl -Credential $pscreds
$sitesInfo = Get-SPOSite
foreach ($site in $sitesInfo) {
Write-Host 'Site collection:' $site.Url
#1. Retrieve and print site info
#Get-SPOSiteGroup -Site $site.Url
$AllWebs = Get-SPOWebs -Url $site.Url -Credential $creds
#2.Retrieve and print webs info (groups Title property in this case)
foreach ($web in $AllWebs) {
$web.Context.Load($web.RoleAssignments.Groups)
$web.Context.ExecuteQuery()
$web.RoleAssignments.Groups.GetEnumerator() | % { Write-Host $_.Title }
}
Write-Host '-----------------------------'
}
Key points:
to retrieve webs within a site collection Get-SPOWebs.ps1 is utilized
here
to get groups per web site Web.RoleAssignments.Groups is used

Powershell remote exchange session missing types

I'd like to collect and process some data from Exchange on remote server using powershell script. Script will be executed on host A, it will create session to host B, inside this session it will create another session - to exchange endpoint.
I'm doing it this way for security reasons, Exchange session needs to be created locally. The issue is that my first session doesn't have exchange data types, type of my $data object
is PSObject, but it should be MailboxDatabase. Is there a way to somehow import data types needed?
$sessWsman = GetOrCreateSession $ip $login $uri $password $configurationName $retryConnectUsingFdqn $uriTemplate $macroMissingWindowsCredentials $macroUnableConnect $macroSessionsDepleted $macroSessionClosed $null
Invoke-Command -Session $sessWsman -Args #("ENG-AUS-SAM-11") -ScriptBlock {
$sessExchange = GetOrCreateSession $ip $login $uri $password $configurationName $retryConnectUsingFdqn $uriTemplate $macroMissingWindowsCredentials $macroUnableConnect $macroSessionsDepleted $macroSessionClosed $sessWsman
if ( -Not ([bool](Get-Command -Name 'Get-MailboxDatabase' -ErrorAction SilentlyContinue)))
{
Import-PSSession $sessExchange -FormatTypeName * -CommandName Get-MailboxDatabase | Out-null
}
$data = Get-MailboxDatabase -Server $HostName -Status
$data.GetType()
}
I tried adding this Add-PSSnapin Microsoft.Exchange* after importing Get-MailboxDatabase, but it didn't helped.