I'm working on a powershell script that modifies config files. I have files like this:
#####################################################
# comment about logentrytimeout
#####################################################
Logentrytimeout= 1800
who should look like this:
#####################################################
# comment about logentrytimeout
#####################################################
Logentrytimeout= 180
disablepostprocessing = 1
segmentstarttimeout = 180
If there is a key set(Logentrytimeout), just update it to the given value. Ignore comments, where the key is mentioned(lines that start with #). The Key is case insensitive.
If the key is not set(disablepostprocessing and segmentstarttimeout), append key and value to the file. My function so far goes like this:
function setConfig( $file, $key, $value )
{
(Get-Content $file) |
Foreach-Object {$_ -replace "^"+$key+".=.+$", $key + " = " + $value } |
Set-Content $file
}
setConfig divider.conf "Logentrytimeout" "180"
setConfig divider.conf "disablepostprocessing" "1"
setConfig divider.conf "segmentstarttimeout" "180"
What is the correct regex?
How do I check if there was a replacement?
If there was no replacement: How can I append $key+" = "+$value to the file then?
Assuming the $key you want to replace is always at the beginning of a line, and that it contains no special regex characters
function setConfig( $file, $key, $value ) {
$content = Get-Content $file
if ( $content -match "^$key\s*=" ) {
$content -replace "^$key\s*=.*", "$key = $value" |
Set-Content $file
} else {
Add-Content $file "$key = $value"
}
}
setConfig "divider.conf" "Logentrytimeout" "180"
If there is no replacement $key = $value will be appended to the file.
Updated version of the functions above with some parametrisation and verbose output if required.
Function Set-FileConfigurationValue()
{
[CmdletBinding(PositionalBinding=$false)]
param(
[Parameter(Mandatory)][string][ValidateScript({Test-Path $_})] $Path,
[Parameter(Mandatory)][string][ValidateNotNullOrEmpty()] $Key,
[Parameter(Mandatory)][string][ValidateNotNullOrEmpty()] $Value,
[Switch] $ReplaceExistingValue,
[Switch] $ReplaceOnly
)
$content = Get-Content -Path $Path
$regreplace = $("(?<=$Key).*?=.*")
$regValue = $("=" + $Value)
if (([regex]::Match((Get-Content $Path),$regreplace)).success)
{
If ($ReplaceExistingValue)
{
Write-Verbose "Replacing configuration Key ""$Key"" in configuration file ""$Path"" with Value ""$Value"""
(Get-Content -Path $Path) | Foreach-Object { [regex]::Replace($_,$regreplace,$regvalue) } | Set-Content $Path
}
else
{
Write-Warning "Key ""$Key"" found in configuration file ""$Path"". To replace this Value specify parameter ""ReplaceExistingValue"""
}
}
elseif (-not $ReplaceOnly)
{
Write-Verbose "Adding configuration Key ""$Key"" to configuration file ""$Path"" using Value ""$Value"""
Add-Content -Path $Path -Value $("`n" + $Key + "=" + $Value)
}
else
{
Write-Warning "Key ""$Key"" not found in configuration file ""$Path"" and parameter ""ReplaceOnly"" has been specified therefore no work done"
}
}
I'd do this:
function setConfig( $file, $key, $value )
{
$regex = '^' + [regex]::escape($key) + '\s*=.+'
$replace = "$key = $value"
$old = get-content $file
$new = $old -replace $regex,$replace
if (compare-object $old $new)
{
Write-Host (compare-object $old $new | ft -auto | out-string) -ForegroundColor Yellow
$new | set-content $file
}
else {
$replace | add-content $file
Write-Host "$replace added to $file" -ForegroundColor Cyan
}
}
Edit: added a replacement bell, and a not match whistle.
Change the function to this:
function Set-Config( $file, $key, $value )
{
$regreplace = $("(?<=$key).*?=.*")
$regvalue = $(" = " + $value)
if (([regex]::Match((Get-Content $file),$regreplace)).success) {
(Get-Content $file) `
|Foreach-Object { [regex]::Replace($_,$regreplace,$regvalue)
} | Set-Content $file
} else {
Add-Content -Path $file -Value $("`n" + $key + " = " + $value)
}
}
Then when you call the function, use this format:
Set-Config -file "divider.conf" -key "Logentrytimeout" -value "180"
Edit: I forgot your requirement of adding the line if it doesn't exist. This will check for the $key, if it exists it will set its value to $value. If it doesn't exist it will add $key = $value to the end of the file. I also renamed the function to be more consistent with power shell naming conventions.
#CarlR Function it's for PowerShell Version 3. This it's the same adapted to PowerShell Version 2.
EDIT: Changed regular expression to fix two bugs on Set-FileConfigurationValue:
If you have one line like this:
; This is a Black line
And you try to do:
Set-FileConfigurationValue $configFile "Black" 20 -ReplaceExistingValue
You get one message about "Replacing" but nothing happens.
If you have two lines like these:
filesTmp=50
Tmp=50
And you try to do:
Set-FileConfigurationValue $configFile "Tmp" 20 -ReplaceExistingValue
You get the two lines changed!
filesTmp=20
Tmp=20
This is the final version:
Function Set-FileConfigurationValue()
{
[CmdletBinding()]
param(
[Parameter(Mandatory=$True)]
[ValidateScript({Test-Path $_})]
[string] $Path,
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string] $Key,
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]$Value,
[Switch] $ReplaceExistingValue,
[Switch] $ReplaceOnly
)
$regmatch= $("^($Key\s*=\s*)(.*)")
$regreplace=$('${1}'+$Value)
if ((Get-Content $Path) -match $regmatch)
{
If ($ReplaceExistingValue)
{
Write-Verbose "Replacing configuration Key ""$Key"" in configuration file ""$Path"" with Value ""$Value"""
(Get-Content -Path $Path) | ForEach-Object { $_ -replace $regmatch,$regreplace } | Set-Content $Path
}
else
{
Write-Warning "Key ""$Key"" found in configuration file ""$Path"". To replace this Value specify parameter ""ReplaceExistingValue"""
}
}
elseif (-not $ReplaceOnly)
{
Write-Verbose "Adding configuration Key ""$Key"" to configuration file ""$Path"" using Value ""$Value"""
Add-Content -Path $Path -Value $("`n" + $Key + "=" + $Value)
}
else
{
Write-Warning "Key ""$Key"" not found in configuration file ""$Path"" and parameter ""ReplaceOnly"" has been specified therefore no work done"
}
}
I've also added a function to read from the config file
Function Get-FileConfigurationValue()
{
[CmdletBinding()]
param(
[Parameter(Mandatory=$True)]
[ValidateScript({Test-Path $_})]
[string] $Path,
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string] $Key,
[Parameter(Mandatory=$False)]
[ValidateNotNullOrEmpty()]
[string]$Default=""
)
# Don't have spaces before key.
# To allow spaces, use "$Key\s*=\s*(.*)"
$regKey = $("^$Key\s*=\s*(.*)")
# Get only last time
$Value = Get-Content -Path $Path | Where {$_ -match $regKey} | Select-Object -last 1 | ForEach-Object { $matches[1] }
if(!$Value) { $Value=$Default }
Return $Value
}
function sed($filespec, $search, $replace)
{
foreach ($file in gci -Recurse $filespec | ? { Select-String $search $_ -Quiet } )
{
(gc $file) |
ForEach-Object {$_ -replace $search, $replace } |
Set-Content $file
}
}
Usage:
sed ".\*.config" "intranet-" "intranetsvcs-"
Related
Hi I'm trying to play with windows updates with PowerShell script, the script works fine but before results it through parsing error.
my script
$Session = New-Object -ComObject Microsoft.Update.Session
$Searcher = $Session.CreateUpdateSearcher()
$HistoryCount = $Searcher.GetTotalHistoryCount()
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa386532%28v=vs.85%29.aspx
$Searcher.QueryHistory(0,$HistoryCount) | ForEach-Object -Process {
$Title = $null
if($_.Title -match "\(KB\d{6,7}\)"){
# Split returns an array of strings
$Title = ($_.Title -split '.*\((?KB\d{6,7})\)')[1]
}else{
$Title = $_.Title
}
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa387095%28v=vs.85%29.aspx
$Result = $null
Switch ($_.ResultCode)
{
0 { $Result = 'NotStarted'}
1 { $Result = 'InProgress' }
2 { $Result = 'Succeeded' }
3 { $Result = 'SucceededWithErrors' }
4 { $Result = 'Failed' }
5 { $Result = 'Aborted' }
default { $Result = $_ }
}
New-Object -TypeName PSObject -Property #{
InstalledOn = Get-Date -Date $_.Date;
Title = $Title;
Name = $_.Title;
Status = $Result
}
} | Sort-Object -Descending:$true -Property nInstalledO |
Select-Object -Property * -ExcludeProperty Name | Format-Table -AutoSize -Wrap
above script works fine but before results it shows some parsing error at line
error:
parsing ".*\((?KB\d{6,7})\)" - Unrecognized grouping construct.
At B:\Clients\SirAhmad\check-updates-history.ps1:9 char:9
+ $Title = ($_.Title -split '.*\((?KB\d{6,7})\)')[1]
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OperationStopped: (:) [], ArgumentException
+ FullyQualifiedErrorId : System.ArgumentException
at line
$Title = ($_.Title -split '.*\((?KB\d{6,7})\)')[1]
Looks regx issues.
Can someone help me out to indicate what is the issue with regix?
The below script was created by the great https://stackoverflow.com/users/9898643/theo to list all orphaned HomeDirectory:
$ServerHomeDirShare = "\\FileServer\HomeDir$"
$filter = "(Enabled -eq 'true')"
# get all user accounts from AD; only SamAccountName required
$users = Get-ADUser -Filter $filter | Select-Object -ExpandProperty SamAccountName
Get-ChildItem -Path $ServerHomeDirShare -Directory |
Where-Object { $users -notcontains ($_.Name -replace '^(\w+\.\w+).*', '$1') } |
Select-Object -Property Name, FullName,
#{ n = 'LastAccessTime'; e = { $_.LastAccessTime.ToString('yyyy-MM-dd HH:mm:ss') } },
#{ n = "Directory Size (MB)"; e = {
Try {
$Size = (Get-ChildItem -Path $_.FullName -Recurse -ErrorAction Stop |
Measure-Object Length -Sum).Sum / 1MB
[math]::Round($Size, 2)
}
Catch {
"ERROR: $($_.Exception.Message)"
}
}
} |
Export-Csv -NoTypeInformation -Path C:\UserProfilesNotExist-Size.csv
However, there is one more issue that needed fixing, to add DOMAIN\Domain Admins AD group as Full Access to the directory ACL, BUT ONLY when the directory is not accessible or throwing error.
$FullAccessADGroup = "DOMAIN\Domain Admins"
function Take-Ownership
{
param (
[String]$Folder
)
takeown.exe /A /F $Folder
$CurrentACL = Get-Acl $Folder
write-host "`n`t...Adding NT Authority\SYSTEM to $Folder" -ForegroundColor Yellow
$SystemACLPermission = "NT AUTHORITY\SYSTEM", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
$SystemAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $SystemACLPermission
$CurrentACL.AddAccessRule($SystemAccessRule)
write-host "`t...Adding Infrastructure Services to $Folder" -ForegroundColor Yellow
$AdminACLPermission = $FullAccessADGroup, "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
$SystemAccessRule = new-object System.Security.AccessControl.FileSystemAccessRule $AdminACLPermission
$CurrentACL.AddAccessRule($SystemAccessRule)
Set-Acl -Path $Folder -AclObject $CurrentACL
}
function Test-Folder($FolderToTest) {
$error.Clear()
$ErrorArray = #()
Get-ChildItem $FolderToTest -Recurse -ErrorAction SilentlyContinue | Select-Object FullName
if ($error) {
$ErrorArray = $error + $ErrorArray
foreach ($err in $ErrorArray) {
if ($err.FullyQualifiedErrorId -eq "DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand") {
Write-Host Unable to access $err.TargetObject -ForegroundColor Red
Write-Host Attempting to take ownership of $err.TargetObject -ForegroundColor Yellow
Take-Ownership($err.TargetObject)
Test-Folder($err.TargetObject)
}
}
}
}
Test-Folder $source
Because even though I am using DOMAIN\Administrator account to execute the script above, I cannot get the directory size or even opened the directory via the UNCPath, this is the error:
ERROR: Access to the path '\\FileServer\HomeDir$\Jane.Liz.V2' is denied.
ERROR: Access to the path '\\FileServer\HomeDir$\Lisa.Chan.V5' is denied.
ERROR: Access to the path '\\FileServer\HomeDir$\Carolline.Marce.V6' is denied.
...
I am building a script that'll check if ArchiveStatus for an Office 365 mailbox is active or not. I am able to pull the data, but my if/else statement doesn't seem to work. This is what I have so far:
$Data = Get-Mailbox -Identity "MailboxName" | ft name,*Archive*
$Data
if ($_.ArchiveStatus -eq $true) {
Write-Host "Archive Enabled"
} else{
Write-Host "Archiving Disabled"
}
No matter what mailbox I search up, the result is always "Archiving Disabled" even if the console shows user enabled.
The current object variable ($_) is only available in a pipeline context. Your if statement is outside a pipeline, so $_ doesn't exist, meaning that $_.ArchiveStatus evaluates to $null, which is interpreted as $false in the comparison.
Change this:
$Data = Get-Mailbox -Identity "MailboxName" | ft name,*Archive*
$Data
if ($_.ArchiveStatus -eq $true) {
Write-Host "Archive Enabled"
} else {
Write-Host "Archiving Disabled"
}
into this:
$Data = Get-Mailbox -Identity "MailboxName"
$Data | ft name,*Archive*
if ($Data.ArchiveStatus -eq $true) {
Write-Host "Archive Enabled"
} else {
Write-Host "Archiving Disabled"
}
and the problem should disappear.
So I was able to figure it out with help from #Ansgar Wiechers. The -eq $true wasn't working because it was either Active or None. When i created the variable for this it worked. The working code is below:
$Data = Get-Mailbox -Identity "MailboxName"
$Data | ft name, ArchiveStatus
$Status = "Active"
if($Data.ArchiveStatus -eq $Status) {
Write-Host "Archive Enabled"
} Else {
Write-Host "Archiving Disabled"
}
Thank you for your help!!
First I made new script that make regex :
$input_path = 'C:\site-download\input.txt'
$output_file = 'C:\site-download\output.txt'
$regex = '(?<month>VPIP<\/span><span class=""right"">\d{2}.\d{1})'
$regex2 = '(?<month>Winrate<\/span><span class=""right"">\d{1}.\d{1})'
$regex3 = '(?<month>PFR<\/span><span class=""right"">\d{2}.\d{1})'
$regex4 = '(?<month>Winnings<\/span><span class=""right"">\-[0-9]{1,9})'
$regex5 = '(?<month>3Bet<\/span><span class=""right"">\d{1}.\d{1})'
Select-String -Path $input_path -Pattern $regex -List | % { $_.Matches} | % { $_.Value } | Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
Select-String -Path $input_path -Pattern $regex2 -List | % { $_.Matches} | % { $_.Value } |Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
Select-String -Path $input_path -Pattern $regex3 -List | % { $_.Matches} | % { $_.Value } | Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
Select-String -Path $input_path -Pattern $regex4 -List | % { $_.Matches} | % { $_.Value } |Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
Select-String -Path $input_path -Pattern $regex5 -List | % { $_.Matches} | % { $_.Value } | Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
Its working good so far.
Second script I found in web (also working good):
Function Register-Watcher {
param ($folder)
$filter = "*.*" #all files
$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $false
EnableRaisingEvents = $true
}
$changeAction = [scriptblock]::Create('
# This is the code which will be executed every time a file change is detected
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file $name was $changeType at $timeStamp"
')
Register-ObjectEvent $Watcher "Changed" -Action $changeAction
}
Register-Watcher "C:\site-download"
So basically I'm working to find out how I can add first script to second.
I tried something this:
Function Register-Watcher {
param ($folder)
$filter = "*.*" #all files
$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $false
EnableRaisingEvents = $true
}
$changeAction = [scriptblock]::Create('
# This is the code which will be executed every time a file change is detected
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file $name was $changeType at $timeStamp"
$input_path = $name
$output_file = 'C:\site-download\output.txt'
$regex = '(?<month>VPIP<\/span><span class=""right"">\d{2}.\d{1})'
$regex2 = '(?<month>Winrate<\/span><span class=""right"">\d{1}.\d{1})'
$regex3 = '(?<month>PFR<\/span><span class=""right"">\d{2}.\d{1})'
$regex4 = '(?<month>Winnings<\/span><span class=""right"">\-[0-9]{1,9})'
$regex5 = '(?<month>3Bet<\/span><span class=""right"">\d{1}.\d{1})'
Select-String -Path $input_path -Pattern $regex -List | % { $_.Matches} | % { $_.Value } | Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
Select-String -Path $input_path -Pattern $regex2 -List | % { $_.Matches} | % { $_.Value } |Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
Select-String -Path $input_path -Pattern $regex3 -List | % { $_.Matches} | % { $_.Value } | Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
Select-String -Path $input_path -Pattern $regex4 -List | % { $_.Matches} | % { $_.Value } |Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
Select-String -Path $input_path -Pattern $regex5 -List | % { $_.Matches} | % { $_.Value } | Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
')
Register-ObjectEvent $Watcher "Changed" -Action $changeAction
}
Register-Watcher "C:\site-download"
But keep getting some errors:
Select-String : Cannot bind argument to parameter 'Path' because it is null.
At line:1 char:21
+ select-string -Path $input_path -Pattern $regex -List | % { $_.Matches} | % { $_ ...
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Select-String], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.SelectStringCommand
Can someone help me out to fix this last script?
Your regex script has single quotes (') in it which are breaking your scriptblock. Replace them with double quotes (").
What i have tested now:
Function Register-Watcher {
param ($folder)
$filter = "*.*" #all files
$watcher = New-Object IO.FileSystemWatcher $folder, $filter -Property #{
IncludeSubdirectories = $false
EnableRaisingEvents = $true
}
$changeAction = [scriptblock]::Create('
# This is the code which will be executed every time a file change is detected
$path = $Event.SourceEventArgs.FullPath
$name = $Event.SourceEventArgs.Name
$changeType = $Event.SourceEventArgs.ChangeType
$timeStamp = $Event.TimeGenerated
Write-Host "The file $name was $changeType at $timeStamp"
')
Register-ObjectEvent $Watcher "Created" -Action $changeAction
}
Register-Watcher "C:\site-download"
Function regex-inout { $input_path = 'C:\site-download\input.txt'
$output_file = "C:\site-download\output.txt"
$regex = "(?<month>VPIP<\/span><span class=""right"">\d{2}.\d{1})"
$regex2 = "(?<month>Winrate<\/span><span class=""right"">\d{1}.\d{1})"
$regex3 = "(?<month>PFR<\/span><span class=""right"">\d{2}.\d{1})"
$regex4 = "(?<month>Winnings<\/span><span class=""right"">\-[0-9]{1,9})"
$regex5 = "(?<month>3Bet<\/span><span class=""right"">\d{1}.\d{1})"
select-string -Path $input_path -Pattern $regex -List | % { $_.Matches} | % { $_.Value } | Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
select-string -Path $input_path -Pattern $regex2 -List | % { $_.Matches} | % { $_.Value } |Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
select-string -Path $input_path -Pattern $regex3 -List | % { $_.Matches} | % { $_.Value } | Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
select-string -Path $input_path -Pattern $regex4 -List | % { $_.Matches} | % { $_.Value } |Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
select-string -Path $input_path -Pattern $regex5 -List | % { $_.Matches} | % { $_.Value } | Foreach-Object {$_ -replace '</span><span class=""right"">', ' = '} | Add-Content $output_file
} regex-inout
Folder watch working good. But where should i move Function regex-inout so that when new files come to folder then this regex start work. At moment only folder watch working and regex didn't do nothing.
Sorry for my bad English.
we have option in ribbon publish - > change but that is not unpublishing subitems .
how can we unpublish item with its subitem for one particular language in sitecore ?
Thanks
Approach 1:
In the Publish ribbon, click the Change button and UNCHECK Publishable on the Item tab. Now delete the parent item with sub-items and the item will be removed from the published DB. Next go back to the item and CHECK Publishable, then publish the item only in the language you want.
Approach 2:
Use the database selector in the Sitecore shell (bottom right corner) and select your publishing target DB (e.g. "web"). GO into that tree, find the item in the language and delete that version. After that you'll need to go to your public site's cache page and clear that cache manually: http://host/sitecore/admin/cache.aspx
Approach 3:
Delete the item in the master DB, publish the parent, restore it form the recycle bin, publish it again live but not in the language you don't want.
some script is also fine :)
just publish site after use it
function GetItemDatasources {
[CmdletBinding()]
param([Item]$Item)
# grab all datasources that are not header and footer elements
return Get-Rendering -Item $item -FinalLayout -Device (Get-LayoutDevice -Default) |
Where-Object { -not [string]::IsNullOrEmpty($_.Datasource)} |
Where-Object { $_.Placeholder -ne 'Above Page Content' } |
Where-Object { $_.Placeholder -ne 'Below Page Content' } |
ForEach-Object { Get-Item "$($item.Database):" -ID $_.Datasource }
# ForEach-Object { Write-Host ($_ | Format-List | Out-String) }
}
$location = get-location
$languages = Get-ChildItem "master:\sitecore\system\Languages"
$currentLanguage = [Sitecore.Context]::Language.Name
$langOptions = #{};
foreach ($lang in $languages) {
$langOptions[$lang.Name] = $lang.Name
}
$result = Read-Variable -Parameters `
#{ Name = "destinationLanguages"; Title="Language(s) for clean up "; Options=$langOptions; Editor="checklist"; },
#{ Name = "includeSubitems"; Value=$false; Title="Include Subitems"; Columns = 4;} `
-Description "Select an languages that should be cleanup" `
-Title "Cleanup Language" -Width 650 -Height 660 -OkButtonName "Proceed" -CancelButtonName "Cancel" -ShowHints
if($result -ne "ok") {
Exit
}
Write-Host "destinationLanguages = $destinationLanguages"
$items = #()
$items += Get-Item $location
# add optional subitems
if ($includeSubitems) {
$items += Get-ChildItem $location -Recurse
}
# Remove any duplicates, based on ID
$items = $items | Sort-Object -Property 'ID' -Unique
$items | ForEach-Object { Write-Host ($_.ItemPath | Sort-Object | Format-List | Out-String) }
$message = "You are about to cleanup <span style='font-weight: bold'>$($items.Count) item(s)</span> with the following options:<br>"
$message += "<br><table>"
$message += "<tr><td style='width: auto'>Languages:</td><td>$destinationLanguages</td></tr>"
$message += "<tr><td style='width: auto'>Include Subitems:</td><td>$includeSubitems</td></tr>"
$message += "</table>"
$message += "<br><p style='font-weight: bold'>Are you sure?</p>"
$proceed = Show-Confirm -Title $message
if ($proceed -ne 'yes') {
Write-Host "Canceling"
Exit
}
Write-Host "Proceeding with execution"
$items | ForEach-Object { Remove-ItemVersion -Item $_ -Language $destinationLanguages -ExcludeLanguage "en*" }
I did this
function GetItemDatasources {
[CmdletBinding()]
param([Item]$Item)
# grab all datasources that are not header and footer elements
return Get-Rendering -Item $item -FinalLayout -Device (Get-LayoutDevice -Default) |
Where-Object { -not [string]::IsNullOrEmpty($_.Datasource)} |
Where-Object { $_.Placeholder -ne 'Above Page Content' } |
Where-Object { $_.Placeholder -ne 'Below Page Content' } |
ForEach-Object { Get-Item "$($item.Database):" -ID $_.Datasource }
# ForEach-Object { Write-Host ($_ | Format-List | Out-String) }
}
$location = get-location
$languages = Get-ChildItem "master:\sitecore\system\Languages"
$currentLanguage = [Sitecore.Context]::Language.Name
$langOptions = #{};
$actions = #{};
$actions["Unpublish"] = "1";
$actions["Publish"] = "";
foreach ($lang in $languages) {
$langOptions[$lang.Name] = $lang.Name
}
$result = Read-Variable -Parameters `
#{ Name = "destinationLanguages"; Title="Language(s) for publich/unpublish"; Options=$langOptions; Editor="checklist"; },
#{ Name = "includeSubitems"; Value=$false; Title="Include Subitems"; Columns = 4;},
#{ Name = "action"; Value="1"; Title="Action"; Options=$actions; Tooltip="Unpublish: Set language as unblishded on all langauge vestions.<br>Publish: Set language as publishded on all langauge vestions."; }`
-Description "Select languages that should be proceed during updates" `
-Title "Language Publish - Unpublish" -Width 650 -Height 660 -OkButtonName "Proceed" -CancelButtonName "Cancel" -ShowHints
if($result -ne "ok") {
Exit
}
Write-Host "destinationLanguages = $destinationLanguages"
$items = #()
$items += Get-Item $location
# add optional subitems
if ($includeSubitems) {
$items += Get-ChildItem $location -Recurse
}
# Remove any duplicates, based on ID
$items = $items | Sort-Object -Property 'ID' -Unique
$items | ForEach-Object { Write-Host ($_.ItemPath | Sort-Object | Format-List | Out-String) }
$message = "You are about to publish/unpublish <span style='font-weight: bold'>$($items.Count) item(s)</span> with the following options:<br>"
$message += "<br><table>"
$message += "<tr><td style='width: auto'>Languages:</td><td>$destinationLanguages</td></tr>"
$message += "<tr><td style='width: auto'>Include Subitems:</td><td>$includeSubitems</td></tr>"
$message += "</table>"
$message += "<br><p style='font-weight: bold'>Are you sure?</p>"
$proceed = Show-Confirm -Title $message
if ($proceed -ne 'yes') {
Write-Host "Canceling"
Exit
}
Write-Host "Proceeding with execution"
$items | ForEach-Object {
$vitems = Get-Item $_.ID -Language $destinationLanguages -Version *
$vitems | ForEach-Object {
$_.Editing.BeginEdit()
$_["__Hide version"] = $action
$_.Editing.EndEdit()
}
}