Create multiple Folders on server then create network share for each as well - regex

I am trying loop through a text file with a list of folder names I would like to create. Then also create a network share to the folder as well.
I am able to create the folder but I am getting stuck on creating the network share.
$folder ='\\networkserver\D$' #Root Directory to place the New folders in.
$routes = get-content 'C:\uncroutes.txt'
foreach ($routes in $routes) {
$newpath = Join-Path "$folder\" -ChildPath $routes
New-Item $newpath -type Directory
foreach ($newpath in $newpath) {
New-SmbShare -Name $newpath -Path $folder -FullAccess Administrator
}
}
This is the error message:
New-SmbShare -Name $newpath -Path $folder -FullAccess Adminis ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (MSFT_SMBShare:ROOT/Microsoft/Windows/SMB/MSFT_SMBShare) [New-SmbShare], CimException
+ FullyQualifiedErrorId : Windows System Error 5,New-SmbShare
Got it working with Help from #Adminofthings. Here is the working code.
$folder ='\\networkserver\D$' #Root Directory to place the New folders in.
$routes = get-content 'C:\uncroutes.txt' #list of folder Names
foreach ($route in $routes) {
$newpath = Join-Path "$folder\" -ChildPath $route
New-Item $newpath -type Directory
foreach ($ShareName in $ShareNames) {
$ShareName = ($route | sls -pattern "([0-9a-zA-Z-_ ]+)$").matches.value
$serverpath = "d:\$route"
New-SmbShare -Name $ShareName -Path $serverpath -FullAccess Administrator
}
}

If I assume correctly about uncroutes.txt and say that it contains a unc path on each line, then you can get the share name by using something like the code below:
$ShareName = ($route | sls -pattern "([0-9a-zA-Z-_ ]+)$").matches.value
Then pass $ShareName into your -name parameter.

Related

Optimizing Script for Downloading Files from Library with Folders

Due to some extenuating circumstances we had to resort to migrating a teams content from one farm to another via locally downloading the files from their lists and shipping them. Unfortunately, this team used folders in their lists VERY heavily. And they wanted to maintain their folder structure for document organization purposes, so I had to come up with a script that could download the contents of a list, folders and all, while also maintaining that folder structure. I have years of SP admin experience, but my PS scripting has always been very basic to intermediate usage at best so I am reaching out to you all to help me optimize this script.
add-pssnapin microsoft.sharepoint.powershell
$w=get-spweb "http://URL"
$tlfolder=$w.getfolder("Old_Surveys")
$subfold=$tlfolder.subfolders|select *|?{$_.name -match "historical"}
$subfolders=$subfold.subfolders
foreach ($subfolder in $subfolders)
{
new-item -path "D:\backups\Old_Surveys\Historical Company Surveys" -name $subfolder.name -itemtype "directory"
#if the 2 level sub folder exists
if ($subfolder.subfolders -ne $null)
{
$subfoldername=$subfolder.name
$subsubfolders=$subfolder.subfolders
foreach ($subsubfolder in $subsubfolders)
{
new-item -path "D:\backups\Old_Surveys\Historical Company Surveys\$subfoldername" -name $subsubfolder.name -itemtype "directory"
# if the 3 level sub folder exists
if ($subsubfolder.subfolders -ne $null)
{
$subsubfoldername=$subsubfolder.name
$subsubsubfolders=$subsubfolder.subfolders
foreach ($subsubsubfolder in $subsubsubfolders)
{
new-item -path "D:\backups\Old_Surveys\Historical Company Surveys\$subfoldername\$subsubfoldername" -name $subsubsubfolder.name -itemtype "directory"
#if the 3 level sub files exists
if ($subsubsubfolder.files -ne $null)
{
$subsubsubfiles=$subsubsubfolder.files
$subsubsubfoldername=$subsubsubfolder.name
foreach ($subsubsubfile in $subsubsubfiles)
{
write-host $subsubsubfile.name
$b=$subsubsubfile.openbinary()
$fs=new-object system.io.filestream(("d:\backups\Old_Surveys\Historical Company Surveys\$subfoldername\$subsubfoldername\$subsubsubfoldername"+$subsubsubfile.name), [system.io.filemode]::create)
$bw=new-object system.io.binarywriter($fs)
$bw.write($b)
$bw.close()
}
}
}
}
if ($subsubfolder.files -ne $null)
{
$subsubfiles=$subsubfolder.files
$subsubfoldername=$subsubfolder.name
foreach ($subsubfile in $subsubfiles)
{
write-host $subsubfile.name
$b=$subsubfile.openbinary()
$fs=new-object system.io.filestream(("d:\backups\Old_Surveys\Historical Company Surveys\$subfoldername\$subsubfoldername\"+$subsubfile.name), [system.io.filemode]::create)
$bw=new-object system.io.binarywriter($fs)
$bw.write($b)
$bw.close()
}
}
}
if ($subfolder.files -ne $null)
{
$subfiles=$subfolder.files
$subfoldername=$subfolder.name
foreach ($subfile in $subfiles)
{
write-host $subfile.name
$b=$subfile.openbinary()
$fs=new-object system.io.filestream(("d:\backups\Old_Surveys\Historical Company Surveys\$subfoldername\"+$subfile.name), [system.io.filemode]::create)
$bw=new-object system.io.binarywriter($fs)
$bw.write($b)
$bw.close()
}
}
}
}
The objective of the code was to iterate down thru any folders, and subfolders of the folders, and create them on the local drive and download any files that are in them at that level. I did this manually for up to 3-sub levels of folders, but if there are more levels lower than that then I would have had to keep manually adding all the code and going even longer. Surely there has to be a better way of doing this?

Get sharepoint lists with more than 5000 items Sharepoint Online Powershell

Can you please help me with a powershell script in sharepoint online that will get all the list with more than 5000 items ? TYIA!
The following PowerShell script for your reference:
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
$SiteURL="https://xx.sharepoint.com/sites/lz"
$UserName="lz#xx.onmicrosoft.com"
$Password = "xx"
$listName ="customlist"
$rowLimit=100
$SecurePassword = $Password | ConvertTo-SecureString -AsPlainText -Force
$Creds = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($UserName,$SecurePassword)
#Bind to Site Collection
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
$ctx.Credentials = $Creds
$list = $ctx.Web.Lists.GetByTitle($listName)
$ctx.Load($list)
# Prepare the query
$query = New-Object Microsoft.SharePoint.Client.CamlQuery
$query.ViewXml = "<View>
<RowLimit>$rowLimit</RowLimit>
</View>"
# An array to hold all of the ListItems
$items = #()
# Get Items from the List until we reach the end
do
{
$listItems = $list.getItems($query)
$ctx.Load($listItems)
$ctx.ExecuteQuery()
$query.ListItemCollectionPosition = $listItems.ListItemCollectionPosition
foreach($item in $listItems)
{
Try
{
# Add each item
$items += $item
}
Catch [System.Exception]
{
# This shouldn't happen, but just in case
Write-Host $_.Exception.Message
}
}
}While($query.ListItemCollectionPosition -ne $null)

Powershell script to open another script as admin

I have a script that I can double click and it'll open other scripts as admin. Works with some things but not everything. For one script, it opens the next window and then immediately closes it. For another, I get this error:
At MYPATH\InstallClient.ps1:33 char:78
+ ... tall_x64.msi" -force -recurse -ErrorAction Stop #Cleans out the file ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The string is missing the terminator: ".
At MYPATH\InstallClient.ps1:27 char:31
+ ForEach ($entry in $computers){ #start of foreach loop
+ ~
Missing closing '}' in statement block or type definition.
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
Below is the script to open a script as an admin:
Function Get-FileName($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.filter = "PS1 (*.ps1)| *.ps1"
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.filename
}
$inputfile = Get-FileName "MYPATH\Scripts"
powershell.exe -noprofile -command "&{start-process powershell -ArgumentList '-NoExit -noprofile -file $inputfile' -verb RunAs}"
This is the script that it gives the previous error for while trying to open:
Function Get-FileName($initialDirectory) #Function to choose a file
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.filter = "MSI (*.msi)| *.msi" #type of files that will be available for selection
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.filename
}
$inputfile = Get-FileName "MyPath" #Directory that is going to open to select a file from
Function Get-FileName($initialDirectory) #Function to choose a file
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.initialDirectory = $initialDirectory
$OpenFileDialog.filter = "CSV (*.csv)| *.csv" #type of files that will be available for selection
$OpenFileDialog.ShowDialog() | Out-Null
$OpenFileDialog.filename
}
$inputfile1 = Get-FileName "MyPath\ServerLists"
$computers = import-csv $inputfile1
ForEach ($entry in $computers){ #start of foreach loop
$computername = $entry.computernames #this saves the single entry under computernames for each entry in csv file
Copy-item $inputfile -container -recurse \\$computername\C$\windows\temp #this copies the msi file that we selected to the computer entry called from the csv file's temp folder
Invoke-Command -Computername $computername –ScriptBlock {Start-process -Wait "C:\windows\temp\ShadowSuiteClientInstall_x64.msi"} | out-null #This starts the msi file that we just copied and waits for the installation to be completed before moving on
If($?){ #If the last command was successful
Echo "Installed ShadowSuiteClientInstall_x64 on $computername."
Remove-Item "\\$computername\C$\windows\temp\ShadowSuiteClientInstall_x64.msi" -force -recurse -ErrorAction Stop #Cleans out the file we copied into the temp folder
}
}
Does anyone have any ideas on why this will open some things fine but give this error for this script and immediately close other scripts without running them? Does anyone have a better way to navigate through scripts and select one to open as admin?
Ok I figured this out. I loaded the script into powershell ISE and I saw that it was compiling it incorrectly. It kept turning the -Scriptblock into an ae symbol instead of the - in front of scriptblock. Weird AF IMO but ok, I fixed it in ISE, which I recommend to anyone struggling with weird compiling errors like this.

Powershell v2.0 - find start path and instance and starting an application

I am trying to write a simple script that stops and then starts a process (Application).
I can stop it fine, but can't find a way to start it again.
The string to start the process should be: "c:\AppFolder\AppName.exe" instance1
my script is:
$appName = "AppName.exe"
$filter = "name like '%"+$appName+"%'"
$result = Get-WmiObject win32_process -Filter $filter
$processid = $result.ProcessId
$command = $result.CommandLine
stop-process $processid
start $command
If I run $result | select * I see that there is an item for CommandLine which is "C:\AppFolder\AppName.exe" instance1
But If I try and do:
$command = $result.CommandLine
stop-process $processid
start $command
I get start-process : This command cannot be executed due to the error: The system cannot find the file specified
But if I manually type into a powershell window start "c:\AppFolder\AppName.exe" instance1 the Application starts fine.
Am I missing something here?
(n.b. it was suggested to me in "powershell v2 - how to get process ID" that I could use
$processid = get-process appName | select -expand id to get the processid, but when I expanded this to get all the items (probably not the correct term?)
in the object I couldn't see an option for CommandLine or similar)
I found the following (but still doesn't work)
$command = Get-WmiObject win32_process -Filter $filter | select -expandproperty CommandLine
write-host $command
This writes "c:\AppFolder\AppName.exe" instance1
start-process $command
But this then results in the following error:
Start-Process : This command cannot be executed due to the error: The system cannot find the file specified
.
At line:11 char:14
+ start-process <<<< $command
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
However, running:
start-process "c:\AppFolder\AppName.exe" instance1
starts the application?
I think I've solved it!! (and it's quite simple really) After much googling. . .
Apparently the start-process cmdlet only accepts a file location.
In order to add an argument (in this case the instance name) I need to use the attribute -ArgumentList
So I need to get the CommandLine item, and split it up, then pass it back in two parts
e.g.
$result = Get-WmiObject win32_process -Filter $filter
$comLine = $result.CommandLine -split"( )"
$comm = $commLine[0]
$inst = $commLine[2]
start-process -FilePath $comm -ArgumentList $inst
And this works as I expected it to.

How I can show and add items to Sharepoint List via Powershell?

hi I want to show and add items in Sharepoint via Powershell (I use for testing a list and a libary)
The name is Powershell-Test
the Url is
http//intranet/departments/it/abt/Lists/Powershell-Test/AllItems.aspx
I enable remote on the Sharepoint Server and make a remote connection to this from my localhost.
Enter-PSSession -ComputerName [sharepoint server] -Authentication Negotiate -Credential [Domain\name]
if((Get-PSSnapin -Name Microsoft.Sharepoint.Powershell -ErrorAction SilentlyContinue) -eq $null)
{
Add-PSSnapin Microsoft.Sharepoint.Powershell
}
$webURL = "http//intranet/departments/it/abt/Lists/"
$listname = "Powershell-Test"
$web = Get-SPWeb $webURL
$web.lists | format-table title
$list = $web.LIsts[$listName]
$list.items | foreach { $_[„Title“] + „`n“ + $_[„Body“] }
The Problem is that I don#t get the connection to the list :(
How I can to this?
I presume you have permission to access the site.
I also presume you don't have a site or subsite with the name "Lists".
I don't think you can use Get-SPWeb with the path "/Lists/" within it (unless the site was named "lists").
Could you try:
if ((Get-PSSnapin -Name Microsoft.SharePoint.Powershell -ErrorAction SilentlyContinue) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.Powershell
}
$siteURL = "http//intranet/departments/it/abt/"
$web = Get-SPWeb $siteURL
$list = $web.Lists["Powershell-Test"]
$list.Items | foreach { $_["Title"] + "`n" + $_["Body"] }