Sitecore Workflow Is Not Working - workflow

I already have an content item (item) with template A.
Template A has not set any workflow initially and I set a new workflow in template's standard value.
If I go to the content item's workflow section, there is only "Default workflow" update. The fields "Workflow" and "State" are empty even I set "Initial State" in the workflow's property, as shown below screenshot. So, workflow process is not working on that item.
However, if I create new item with the template already set workflow, I could see all filled workflow fields based on its initial workflow setting. So, workflow process is perfectly working.
I have a number of pages without workflow setting and I'm about to assign new workflow in its templates.
How can I solve this issue???????

I used Powershell Script and it looks like this.
It updates the empty field and perfectly works.
##################################################################
## 1. Set default workflow state in template's standard value ##
## 2. Before running script, must set correct Context Item ##
##################################################################
function SetWorkflow($item)
{
## Update only items assigned __Default workflow
if ($item."__Default workflow" -eq "{A5BC37E7-ED96-4C1E-8590-A26E64DB55EA}") {
$item.__Workflow = "{A5BC37E7-ED96-4C1E-8590-A26E64DB55EA}";
$item."__Workflow state" = "{190B1C84-F1BE-47ED-AA41-F42193D9C8FC}";
}
}
## Update correct workflow information.
get-item . -Language * | foreach-object { SetWorkFlow($_) }
get-childitem . -recurse -Language * | foreach-object { SetWorkFlow($_) }
## Show Updated Result
get-item . -Language * | Format-Table Id, Name, Language, __Workflow, "__Workflow state", "__Default workflow"
get-childitem . -recurse -Language * | Format-Table Id, Name, Language, __Workflow, "__Workflow state", "__Default workflow"

When you set the default workflow value on a standard values item it does not automatically and go through and add existing item versions into a specific workflow state. This is because any content that was previously published would become unpublished as it would go to the default state of the workflow, which is typically a draft state.
The next time you add a version to the item that now has workflow (either explicitly or by "editing" as a lower level user), its state should be set to draft as you'd expect.
If you need to migrate existing versions of items into workflow at particular state you will probably need to do this via code.

Related

Powershell - Replace add_Click link on LinkLabel

I am creating a PowerShell GUI that uses a link label. My code for this link is
$ExLinkLabel = New-Object System.Windows.Forms.LinkLabel
$ExLinkLabel.Location = New-Object System.Drawing.Size(15,130)
$ExLinkLabel.Size = New-Object System.Drawing.Size(150,20)
$ExLinkLabel.LinkColor = "BLUE"
$ExLinkLabel.ActiveLinkColor = "RED"
$ExLinkLabel.Text = "Link Example"
$ExLinkLabel.add_Click({[system.Diagnostics.Process]::start("https://google.com")})
$Form.Controls.Add($ExLinkLabel)
Now say I want to change it another website later in the code based on certain conditions, I tried doing this:
$ExLinkLabel.add_Click({[system.Diagnostics.Process]::start("https://yahoo.com")})
The problem that this now has two links open, both google and then yahoo.
Is there a way to clear or just replace that first link with my new one?
Thank you
Adding an event handler with an .add_<EventName>() method call does just that: It adds an additional event handler, of which there can be many.
In order to replace an event handler, you must first remove its old incarnation with .remove_<EventName>(), and then add the new incarnation with .add_<EventName>().
To that end, you must store the original incarnation in a variable that you can later pass to the .remove_EventName>() call:
# Define the original event handler, store it in a variable,
# and add it to the control.
$currEventHandler = { Start-Process https://google.com }
$ExLinkLabel.add_Click($currEventHandler)
# ...
# Remove the current event handler...
$ExLinkLabel.remove_Click($currEventHandler)
# ... and add the new one:
$currEventHandler = { Start-Process https://yahoo.com }
$ExLinkLabel.add_Click($currEventHandler)
Note that I've replaced [system.Diagnostics.Process]::start($url) with a simpler, PowerShell-idiomatic call to the Start-Process cmdlet.
In your simple case, where the two event handlers only differ by the URL they open, consider the alternative recommended by Theo:
Retain the original event handler and make it retrieve the URL to open from a variable defined outside the event handler, namely in the script scope. That way, all you need to do is to update the variable.
# Set the original URL
$url = 'https://google.com'
# Due to PowerShell's dynamic scoping, the event-handler script
# block - even though it runs in a *child* scope - sees the
# script scope's definition of variable $url
# You can make this cross-scope access explicit by using $script:url
# (If you wanted to *update* the variable from inside the child
# scope $script:url *must* be used.)
$ExLinkLabel.add_Click({ Start-Process $url })
# ...
# Update the variable, after which the event handler will
# use the new URL.
$url = 'https://yahoo.com'

Disabling Installshield's Next button with powershell

I have an Installshield project that uses powershell custom actions.
In one of my dialogs, I'm asking from the user to enter username and password, then I validate the credentials (with powershell) and I want to enable the Next button only if the credentials were correct.
Can this be achieved with powershell action item? The reason I'm using powershell is that I don't know InstallScript at all.
Here is my powershell script so far:
Function Test-UserCredential {
Param($username, $password)
Add-Type -AssemblyName System.DirectoryServices.AccountManagement
$ct = [System.DirectoryServices.AccountManagement.ContextType]::Machine, $env:computername
$opt = [System.DirectoryServices.AccountManagement.ContextOptions]::SimpleBind
$pc = New-Object System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ct
$Result = $pc.ValidateCredentials($username, $password).ToString()
$Result
}
$comp_username = Get-Property -Name COMPUTER_USERNAME
$comp_password = Get-Property -Name COMPUTER_PASSWORD
$result = Test-UserCredential -username $comp_username -password $comp_password
if ($result)
{
#Enable "Next" button
}
else
{
#Disable "Next" button
}
Thanks.
There are three things you will have to do.
Choose a property that tracks whether the Next button should be enabled, and set that from your PowerShell. Typically you will set it to "1" or "" (empty string) for ease in the next step.
Create Control Conditions in the dialog editor that Enable and Disable the Next button referencing the property as your condition.
Separately trigger the UI to update after the powershell action completes. Unfortunately the UI does not evaluate control conditions after all property changes; it only does so after it changes a property it thinks is related. So the easiest way to do this is to add a Set Property control event that sets the property.
Note that for clarity of step 3's relevance, it can be useful to split this into two separate properties; set one in the powershell, reflect that into another in the Set Property control event, and have control conditions that read the latter.

Regularly check a property of a SharePoint item with Powershell

I am using powershell to check, if a SharePoint I just added has changed. To do so, I first add the item via
$spFile = $spFiles.Add(...)
after that I regularly do this:
$spFile.Item["propertyName"]
The result is the same every time, even if I change the property in SharePoint. So I guess I have to refresh the item in Powershell. How can this be done?
You need to get the document library once again and then only you can get the changed value. It stores in cache, Something like this you need to do
$library = $web.Lists["DocumentLibrary"]
$spFiles= $library.Items | where {$_.FileSystemObjectType -eq "File"}
foreach ($spFile in $spFiles) {
$spFile.Item["propertyName"]
}

New & renamed workflows with existing content

I have a site with a custom content type Content, which initially had a single workflow attached, content_workflow. There are several thousand existing instances of Content.
I now have a need to add a second workflow to this type, content_beta_workflow. How can I update all existing content to be part of the new workflow?
On a related note: if I want rename the initial workflow to content_alpha_workflow, how can I update all existing content to reflect this change?
If you are simply changing from one workflow to the other, follow these steps:
Go to Site Setup > Types
Select your custom content type from the drop down menu, the page will update to display the current workflow
Select your new workflow from the dropdown, a map will be generated showing each state in the current workflow
For each state, select the state in your new workflow that most closely matches (or is most appropriate)
When you save, all objects of your custom site will be updated to use the new workflow. For each state in the map from the original workflow, existing content in that state will be put into the state you chose in step 4 above. Security settings will be re-indexed and you are done.
As for renaming the old workflow, you can do so in the portal_workflow tool in the ZMI. But only change the human-facing Title of the workflow. Changing the ID may have side effects for the workflow history of your content.
edited
Okay, I see from your comment that you are looking to add a new workflow to a type in addition to the one it already has. Here's a bit of sample code to accomplish that:
my_type = 'Content' # This is your content portal_type name
my_wf = 'content_workflow_beta'
wf_chain = list(wf_tool.getChainForPortalType(my_type))
if my_wf not in wf_chain:
wf_chain.append(my_wf)
wf_tool.setChainForPortalTypes([my_type], wf_chain)
You can add this code in an upgrade step for the package that defines your content type and workflows. Add a call to updateRoleMappings on the workflow tool and you'll be set to use the new workflow through the standard Plone UI in addition to your original workflow.
As you've already found, you can also manually update the workflow history of all objects to rename workflow ID, but that's a pretty invasive step.
As workflow_history is a dict property on each content item, it was a case of adding or updating suitable items as required. First, I copied the GenericSetup for content_workflow to content_alpha_workflow. Next, I created content_beta_workflow and added it to the profile. Then I wrote the following upgrade step:
import logging
from DateTime import DateTime
def modify_content_workflow_history(context, logger=None):
if logger is None: logger = logging.getLogger('my.product')
# import the new workflows
context.portal_setup.runImportStepFromProfile('profile-my.product:default', 'workflow')
# set up some defaults for the new records
_history_defaults = dict(
action = None,
actor = 'admin',
comments = 'automatically created by update v2',
time = DateTime(),
)
_alpha_defaults = dict(review_state = 'alpha_state_1', **_history_defaults)
_beta_defaults = dict(review_state = 'beta_state_1', **_history_defaults)
for parent in context.parents.values():
for content in parent.content.values():
# don't acquire the parent's history
if 'parent_workflow' in content.workflow_history:
content.workflow_history = {}
# copy content_workflow to content_alpha_workflow
if 'content_workflow' in content.workflow_history:
alpha_defaults = context.workflow_history['content_workflow']
del content.workflow_history['content_workflow']
else:
alpha_defaults = (_alpha_defaults,) # must be a tuple
content.workflow_history['ctcc_content_alpha_workflow'] = alpha_defaults
# create the beta workflow with a modified actor
beta_defaults = dict(**_beta_defaults)
beta_defaults['actor'] = u'%suser' % parent.id
content.workflow_history['ctcc_content_beta_workflow'] = (beta_defaults,)
logger.info('Content workflow history updated')

Invoke SharePoint Workflow after EventReceiver

i got a question regarding sharepoint workflows and event receivers. i got an event receiver that is setting metadata on an element. after that, i use a workflow to copy item metadata to a list. unfortunately the workflow does not copy the metadata set by the event receiver. i think because it is executed before the event receiver. is there a possibility to change the order, so that the workflow will execute after the event receiver? the receiver ist bound to the ItemAdded and ItemUpdated Events i a syncrounous manner.
Thank you for your help!
Patrick
You can use SPWorkFlowAssociation to run workflow that associate with List or Content Type .
Example ( run workflow after adding item)
public override void ItemAdded(SPItemEventProperties properties)
{
SPList parentList = properties.ListItem.ParentList;
SPWorkflowAssociation associationTemplate =
parentList.WorkflowAssociations.GetAssociationByName("Your Workflow Name",
new CultureInfo
(Convert.ToInt32(parentList.ParentWeb.RegionalSettings.LocaleId)));
SPSite siteCollection = properties.ListItem.ParentList.ParentWeb.Site;
siteCollection.WorkflowManager.StartWorkflow(properties.ListItem,
associationTemplate, String.Empty);
}
More information about SPWorkflowAssociation Check the below link
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.workflow.spworkflowassociation.aspx
SPListItem:
The "Synchronous" events (-ing ending like ItemAdd*ing*), are always executed before the workflow.
The "Asynchronous" events (-ed ending like ItemAdd*ed*), are always executed after the execution of the workflow.
So, you have to set the "Synchronization" property of the Elements.xml file equal to "Synchronous" and the workflow will always be executed after the event receiver.
ATTENTION: Events Added and Updated run asynchronously by default, so you have to do the change in the Elements.xml .