For navigation purpose, we use Term sets.
I need to create a PowerShell to get term sets with URLs from specific term groups.
Here is my script
Set-ExecutionPolicy -Scope CurrentUser Unrestricted
#Specify admin user and SharePoint site URL
##update login
$User = "corporate\spuser"
##update siteUrl
$Site = "http://sp13"
#Adding references to SharePoint client assemblies
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "c:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Taxonomy.dll"
$Pwd = "xvcx23423"
$GroupName = "India"
$TermSetName ="India_Global"
#Recursive function to get terms
function GetTerms([Microsoft.SharePoint.Client.Taxonomy.Term] $Term,[String]$ParentTerm,[int] $Level)
{
$Terms = $Term.Terms;
$Context.Load($Terms)
$Context.ExecuteQuery();
if($ParentTerm)
{
$ParentTerm = $ParentTerm + "," + $Term.Name;
}
else
{
$ParentTerm = $Term.Name;
}
Foreach ($SubTerm in $Terms)
{
$Level = $Level + 1;
#up to 7 terms levels are written
$NumofCommas = 7 - $Level;
$commas ="";
For ($i=0; $i -lt $NumofCommas; $i++)
{
$commas = $commas + ",";
}
$file.Writeline("," + "," + "," + "," + $Term.Description + "," + $ParentTerm + "," + $SubTerm.Name + $commas );
GetTerms -Term $SubTerm -ParentTerm $ParentTerm -Level $Level;
}
}
$Context = New-Object Microsoft.SharePoint.Client.ClientContext($Site)
$Credentials = New-Object System.Net.NetworkCredential($User,$Pwd);
$Context.Credentials = $Credentials
$MMS = [Microsoft.SharePoint.Client.Taxonomy.TaxonomySession]::GetTaxonomySession($Context)
$Context.Load($MMS)
$Context.ExecuteQuery()
#Get Term Stores
$TermStores = $MMS.TermStores
$Context.Load($TermStores)
$Context.ExecuteQuery()
$TermStore = $TermStores[0]
$Context.Load($TermStore)
$Context.ExecuteQuery()
#Get Groups
$Group = $TermStore.Groups.GetByName($GroupName)
$Context.Load($Group)
$Context.ExecuteQuery()
#Bind to Term Set
$TermSet = $Group.TermSets.GetByName($TermSetName)
$Context.Load($TermSet)
$Context.ExecuteQuery()
#Create the file and add headings
$OutputFile = "Output File Path1.csv"
$file = New-Object System.IO.StreamWriter($OutputFile)
$file.Writeline("Term Set Name,Term Set Description,LCID,Available for Tagging,Term Description,Level 1 Term,Level 2 Term,Level 3 Term,Level 4 Term,Level 5 Term,Level 6 Term,Level 7 Term");
$Terms = $TermSet.Terms
$Context.Load($Terms);
$Context.ExecuteQuery();
$lineNum = 1;
Foreach ($Term in $Terms)
{
if($lineNum -eq 1)
{
##output term properties on first line only
$file.Writeline($TermSet.Name + "," + $TermSet.Description + "," + $TermStore.DefaultLanguage + "," + $TermSet.IsAvailableForTagging + "," + $Term.Description + "," + $Term.Name + "," + "," + "," + "," + "," + "," );
}
else
{
$file.Writeline("," + "," + "," + "," + $Term.Description + "," + $Term.Name + "," + "," + "," + "," + "," + "," );
}
$lineNum = $lineNum + 1;
$TermTreeLevel = 1;
GetTerms -Term $Term -Level $TermTreeLevel -ParentTerm "";
}
$file.Flush();
$file.Close();
Any idea how to get the URLs of the term set.
Is there any better approach to export/import term set of a specific group.
You can get the term set friendly URL using TaxonomySession:
SPSite site = SPSite.Current.Site;
TaxonomySession servis = new TaxonomySession(site);
siteNavigationStore = servis.DefaultSiteCollectionTermStore;
siteNavigationGroup = sitenavigationstore.GetSiteCollectionGroup(site);
siteNavigationSet = sitenavigationgrup.TermSets["Term Set Name"];
NavigationTerm navigatedTerm = NavigationTerm.GetAsResolvedByWeb(navigationterm, site.RootWeb, StandardNavigationProviderNames.GlobalNavigationTaxonomyProvider);
navigatedTerm.GetWebRelativeFriendlyUrl();
GetWebRelativeFriendlyUrl return your friendly url
Related
I am writing a script to query a SQL server to aggregate data that I can use to search through various directories. If the folder does not exist it should write the path that does not exist to a text file at the end of the code.
I created an array to prefill the strings of the paths which are completed by using the SQL data. I'm coming into the issue of input sting was not in a correct format and the issue of it not correctly filling the text document. It will fill the text document with folders that both do and do not exist.
I have tried various configurations. I believe the array could be my issue but I am currently unsure.
Error is as follows:
Cannot convert value "Walker" to type "System.Int32". Error: "Input string was not in a correct format."
At \\cottonwood\users\C.B\My Documents\Untitled1.ps1:36 char:115
+ ... Address)#> + $($Row.'Last Name') + $array[$i]
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastFromStringToInteger
Code is as follows:
$SQLServer = "REDWOOD" #use Server\Instance for named SQL instances!
$SQLDBName = "MARS"
$SqlQuery = "select Account, IsActive, [Last Name] FROM vw_loans WHERE ( Account NOT IN ('100040A','100041A','100044A','100044B','100044C','100079A','100040A','100041A','100044A','100044B','100044C','100079A','100153B','100413B')) AND LEFT(Account,1)<>'_' AND (Account NOT like '%B%') AND (LoanStatus != 'PRELIM') ORDER BY Account"
$SqlConnection = New-Object System.Data.SqlClient.SqlConnection
$SqlConnection.ConnectionString = "Server = $SQLServer; Database = $SQLDBName; Integrated Security = True"
$SqlCmd = New-Object System.Data.SqlClient.SqlCommand
$SqlCmd.CommandText = $SqlQuery
$SqlCmd.Connection = $SqlConnection
$SqlAdapter = New-Object System.Data.SqlClient.SqlDataAdapter
$SqlAdapter.SelectCommand = $SqlCmd
$DataSet = New-Object System.Data.DataSet
$SqlAdapter.Fill($DataSet)
$SqlConnection.Close()
clear
$DataSet.Tables[0]
$array = "\I. Originations\Final Originations Package","\II. Servicing\A. Communications", "\II. Servicing\B. Foreclosure Documents","\II. Servicing\C. Bankruptcy Documents", "\II. Servicing\D. Amendments & Extensions", "\II. Servicing\E. Property", "\II. Servicing\F. Previous Servicer Data", "\III. Loan Documents", "\IV. Taxes, Insurance, HOA\HOA", "\IV. Taxes, Insurance, HOA\Insurance","\IV. Taxes, Insurance, HOA\Insurance\PMI","\IV. Taxes, Insurance, HOA\Taxes"
foreach ($Row in $dataset.Tables[0].Rows)
{
for($i=0;$i -lt $array.Length; $i++)
{
if($Row.IsActive -eq $True)
{
$CorrPath = "U:\Shared\Loan Documents - Active\" + $($Row.Account) + " - " + <#$(Row.Address)#> + $($Row.'Last Name') + $array[$i]
}
if($Row.IsActive -eq $False)
{
$CorrPath = "U:\Shared\Loan Documents - Inactive\" + $($Row.Account) + " - " + <#$(Row.Address)#> + $($Row.'Last Name') + $array[$i]
}
$FileExist = Test-Path $CorrPath
If($FileExist -eq $False)
{Add-Content $Corrpath -Path "\\cottonwood\users\IT\Missing Folder Location\MissingSubFolders.txt"}
}
}
Looks to me like the parser is confused by what the + operator is supposed to be doing. It's trying to add when it should be concatenating. Try forcing everything to a string:
if($Row.IsActive) {
$CorrPath = "U:\Shared\Loan Documents - Active\" + $($Row.Account.ToString()) + " - " + <#$(Row.Address)#> + $($Row.'Last Name'.ToString()) + $array[$i].ToString()
} else {
$CorrPath = "U:\Shared\Loan Documents - Inactive\" + $($Row.Account.ToString()) + " - " + <#$(Row.Address)#> + $($Row.'Last Name'.ToString()) + $array[$i].ToString()
}
Or else try formatting the filename differently:
$CorrPath = "U:\Shared\Loan Documents - Active\{0} - {1}{2}" -f $Row.Account,$Row.'Last Name',$array[$i]
I have a script that sends an email when files are about to reach their max size.
The problem is, that I can't implement a validation check of what the script should do when a file is not found at the given path.
I know that I should implement:
if(!(Test-Path $item.Path))
{
"The file " + $item.Name + " is not found! <br />"
}
But I don't know where to place it exactly (since I'm getting errors all over the place).
The Code:
I start with retrieving the files from a config file:
$list = foreach ($file in $files)
{
$f = Get-Item $file.Path
New-Object -Type PSObject -Property #{
Name = $f.Name
Path = $file.Path
Size = ($f.Length/$byteSize)
}
}
then I loop through the file list and check their size:
foreach ($item in $list)
{
if($item.Size -gt $item.TriggerSize -And (Test-Path $item.Path))
{
#Write-Host $item.Name "Warning! File has reached it's max limit ("$item.Size.ToString(".00")"), The max size is" $item.MaxSize". The trigger size is: " $item.TriggerSize "`r`n"
$body +=
"The file " + $item.Name + " is reaching his max size!
<br /> Current size: <b>"+$item.Size.ToString(".00") + " " + $byteSize.Substring(1) + "</b>" +
"<br /> Maximum size: " + $item.MaxSize + " " + $byteSize.Substring(1) + "<br /><br />"
}
}
I tried implementing my error check on these places:
$list = foreach ($file in $files)
{
if(!(Test-Path $item.Path))
{
"The file " + $item.Name + " is not found! <br />"
}
$f = Get-Item $file.Path
New-Object -Type PSObject -Property #{
Name = $f.Name
Path = $file.Path
Size = ($f.Length/$byteSize)
}
}
and here
foreach ($item in $list)
{
if($item.Size -gt $item.TriggerSize -And (Test-Path $item.Path))
{
#Write-Host $item.Name "Warning! File has reached it's max limit ("$item.Size.ToString(".00")"), The max size is" $item.MaxSize". The trigger size is: " $item.TriggerSize "`r`n"
$body +=
"The file " + $item.Name + " is reaching his max size!
<br /> Current size: <b>"+$item.Size.ToString(".00") + " " + $byteSize.Substring(1) + "</b>" +
"<br /> Maximum size: " + $item.MaxSize + " " + $byteSize.Substring(1) + "<br /><br />"
}
if(!(Test-Path $item.Path))
{
"The file " + $item.Name + " is not found! <br />"
}
}
But I keep getting the error that it's at Get-Item that it can't find a file:
the name of the file that I wrote with a false path on purpose:
file123.exe
Error (at the line of the if(!(Test-Path $file.path)):
Get-Item : Cannot find path 'file123.exe' because it does not exist.
You are trying to error-handle but then your code still passes control to main logic. Instead, you should develop your control flow so that Get-Item will be called only when Test-Path returns true.
$list = foreach ($file in $files)
{
if (Test-Path $file.Path) {
$f = Get-Item $file.Path
New-Object -Type PSObject -Property #{
Name = $f.Name
Path = $f.Path
Size = ($f.Length/$byteSize)
}
} else {
"The file " + $file.path + " is not found! <br />"
}
}
And finally, PROOFREAD YOUR CODE! You've got $item.path tested but $file.path accessed. Given your foreach loop, you should have $file.path at both places.
You are only checking for file's existence and not catching not found exception. Here's a pseudo that should work:
foreach ($file in $files) {
try {
if (!(Test-Path $file.Path)) {
throw "File $($file.Path) not found"
}
# Rest of the logic
}
catch {
# log error $_.Exception.Message
}
}
Update: Send email whether file exists or not. This is pseudo, excuse syntax please.
Refactor the email sending functionality in separate method, say Send-Email($content). Then:
foreach file in files {
if !(Test-Path file.path) {
Send-Email -content "File $($file) does does not exist"
}
else {
// your logic here
if file.size > threshold {
Send-Email -content "File $($file) exceeded threshold size"
}
}
}
I´m working on a code that is supposed to import-csv - change the content, and then export to csv.
I´ve tried to export with Export-Csv - but it only writes the lenght of the string
I also tried with StreamWriter - but it only writes $Resultat once
I am new to PowerShell :-)
$workfile = import-csv "X:\powershell\converter\test.csv" -Delimiter ';'
ForEach ($item in $workfile)
{
$Id = $item.("ID")
$Maaler = $item.("Maaler")
$Fra = $item.("Fra")
$Til = $item.("Til")
#Dato gymnastik
$Tilto = $item.("Til")
$Tilto = $Tilto.substring(0,10)
$Til = $Til.substring($Til.length - 8, 8)
$Forbrug = $item.("Forbrug")
$Enhed = $item.("Enhed")
$aflaesningstype = $item.("Aflæsningstype?")
$T = ".000+02:00"
$Resultat = $Tilto + "T" + $Til + $T + ',"' + $Maaler + '","' + '","' + '","' + '","' + '","' + $Forbrug + '","' + $Enhed + '","' + '255"'
Write-output "$Resultat"
}
$Resultat | Export-Csv "X:\powershell\behandlet\Output $(get-date -f dd-MM-yyyy-hh-mm-ss).csv" -Delimiter ',' -NoType
#$fhStream = [System.IO.StreamWriter] "X:\powershell\behandlet\Output $(get-date -f dd-MM-yyyy-HH-mm-ss).csv"
#$fhStream.WriteLine($Resultat)
#$fhStream.Close()
The Write-output shows the output in the right way
Can anyone see what I am doing wrong ?
Try this:
$workfile = import-csv "X:\powershell\converter\test.csv" -Delimiter ';'
$result = New-Object System.Collections.ArrayList
ForEach ($item in $workfile)
{
$Id = $item.("ID")
$Maaler = $item.("Maaler")
$Fra = $item.("Fra")
$Til = $item.("Til")
#Dato gymnastik
$Tilto = $item.("Til")
$Tilto = $Tilto.substring(0,10)
$Til = $Til.substring($Til.length - 8, 8)
$Forbrug = $item.("Forbrug")
$Enhed = $item.("Enhed")
$aflaesningstype = $item.("Aflæsningstype?")
$T = ".000+02:00"
$result += $Tilto + "T" + $Til + $T + ',"' + $Maaler + '","' + '","' + '","' + '","' + '","' + $Forbrug + '","' + $Enhed + '","' + '255"'
}
$result | Out-File "X:\powershell\behandlet\Output $(get-date -f dd-MM-yyyy-hh-mm-ss).csv"
I am attempting to download attachments from emails with certain subject lines in an inbox, then delete the email.
There are about a dozen different subject lines in total.
I want to schedule this process to run every 10 minutes or so, so I'd like to keep any processing overheads to a minimum..
Current script is in PowerShell (based on this), but I'm unsure how I could make it loop through a bunch of different subjects. I could just repeat the whole script for each subject, but it's quite inefficient this way..
I'm open to non-PowerShell alternatives too..
$MailboxName = "mailbox#address.com"
$Subject = #("Subject1")
$downloadDirectory = "c:\temp"
Function FindTargetFolder($FolderPath){
$tfTargetidRoot = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$MailboxName)
$tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$tfTargetidRoot)
for ($lint = 1; $lint -lt $pfArray.Length; $lint++) {
$pfArray[$lint]
$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1)
$SfSearchFilter = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+isEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$pfArray[$lint])
$findFolderResults = $service.FindFolders($tfTargetFolder.Id,$SfSearchFilter,$fvFolderView)
if ($findFolderResults.TotalCount -gt 0){
foreach($folder in $findFolderResults.Folders){
$tfTargetFolder = $folder
}
}
else{
"Error Folder Not Found"
$tfTargetFolder = $null
break
}
}
$Global:findFolder = $tfTargetFolder
}
$dllpath = "C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll"
$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2007_SP1)
$windowsIdentity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
$sidbind = "LDAP://<SID=" + $windowsIdentity.user.Value.ToString() + ">"
$aceuser = [ADSI]$sidbind
$uri=[system.URI] "https://webmail.company.com.au/EWS/Exchange.asmx"
$service.Url = $uri
FindTargetFolder($ProcessedFolderPath)
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Inbox,$MailboxName)
$InboxFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid)
$Sfsub = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.ItemSchema]::Subject, $Subject[0])
$Sfha = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::HasAttachments, $true)
$sfCollection = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
$sfCollection.add($Sfsub)
$sfCollection.add($Sfha)
$view = new-object Microsoft.Exchange.WebServices.Data.ItemView(2000)
$frFolderResult = $InboxFolder.FindItems($sfCollection,$view)
foreach ($miMailItems in $frFolderResult.Items){
$miMailItems.Subject
$miMailItems.Load()
foreach($attach in $miMailItems.Attachments){
$attach.Load()
$fiFile = new-object System.IO.FileStream(($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($attach.Content, 0, $attach.Content.Length)
$fiFile.Close()
write-host "Downloaded Attachment : " + (($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()))
}
$miMailItems.isread = $true
$miMailItems.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
$miMailItems.delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::MoveToDeletedItems)
}
Okay, here's what I've got:
$Subjects = #(
'newIM_IPSC',
'newCM_IPSC',
'CNSDI',
'SMEC_Incident_SLM',
'Incident_SLM',
'MEC_Incident_WorkInfo',
'SMEC_Incident_Header',
'SMEC_SR_Header'
)
[regex]$SubjectRegex = ‘^(?i)(‘ + (($Subjects |foreach {[regex]::escape($_)}) –join “|”) + ‘)$’
Then:
foreach($attach in $miMailItems.Attachments){
foreach ($miMailItems in $frFolderResult.Items){
if ($miMailItems.Subject -match $SubjectRegex)
{
$miMailItems.Load()
foreach($attach in $miMailItems.Attachments){
$attach.Load()
$fiFile = new-object System.IO.FileStream(($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()), [System.IO.FileMode]::Create)
$fiFile.Write($attach.Content, 0, $attach.Content.Length)
$fiFile.Close()
write-host "Downloaded Attachment : " + (($downloadDirectory + “\” + (Get-Date -Format "yyMMdd") + "_" + $attach.Name.ToString()))
}
$miMailItems.isread = $true
$miMailItems.Update([Microsoft.Exchange.WebServices.Data.ConflictResolutionMode]::AlwaysOverwrite)
$miMailItems.delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::MoveToDeletedItems)
}
}
Add or remove subject lines from the $Subjects array as needed.
An explanation of the bits that are building the regex can be found here:
http://blogs.technet.com/b/heyscriptingguy/archive/2011/02/18/speed-up-array-comparisons-in-powershell-with-a-runtime-regex.aspx
How do I set a metadata (say CustomerID or Skills) with PowerShell? I am trying to fill CustID. Please suggest.....
$siteURL="http://Server"
$site=Get-SPSite $siteURL
$web=$site.RootWeb
$collFiles=$web.GetFolder("DocLib_OR_List").Files
$count=$collFiles.Count
while($count -ne 0)
{
$CustID= $collFiles[$count-1]["CustomerID"]
so forth......
}
Solved it. Working code:
$siteURL="http://Server"
$docLib = "My Doc Lib"
$site=Get-SPSite $siteURL
$web=$site.RootWeb
$collFiles=$web.GetFolder($docLib).Files
$count=$collFiles.Count
while($count -ne 0)
{
$item = $collFiles[$count-1].Item
$DocSet = $item["Region"]
Write-Host "$DocSet is the doc set. $collFiles[$count-1].Name is name"
$collFiles[$count-1].MoveTo($siteURL + "/" + $docLib + "/" + $DocSet + "/" + $collFiles[$count-1].Name, $true)
$count--
}
This is the final working code.
$siteURL="http://Server"
$docLib = "My Doc Lib"
$site=Get-SPSite $siteURL
$web=$site.RootWeb
$collFiles=$web.GetFolder($docLib).Files
$count=$collFiles.Count
while($count -ne 0)
{
$item = $collFiles[$count-1].Item
$DocSet = $item["Region"]
Write-Host "$DocSet is the doc set. $collFiles[$count-1].Name is name"
$collFiles[$count-1].MoveTo($siteURL + "/" + $docLib + "/" + $DocSet + "/" + $collFiles[$count-1].Name, $true)
$count--
}