I did the following:
$oldWorkflow="MyOldWorkflow";
$oldAssoc=$list.WorkflowAssociations.GetAssociationByName($oldWorkflow,"en-US");
$list.RemoveWorkflowAssociation($oldAssoc);
After that I can see that the workflow does not exist anymore. But on each Item that had the workflow before I receive an error when trying to display the workflows:
Getting Error Message for Exception System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.ArgumentException: Column 'Reservat' doesn't exist
I never had a column with that name. After adding that column manually to the list, the error messages changed to:
Application error when access /_layouts/15/Workflow.aspx, Error=Object reference not set to an instance of an object.
Any chance to solve this mess? (The old workflow does NOT exist anymore as WSP)
UPDATE:
I can still find the workflows using Powershell:
foreach ($wf in $item.Workflows)
if ($wf.ParentAssociation.Name -eq $oldWorkflow)
...
But in the same time $list.WorkflowAssociations.GetAssociationByName does NOT return the workflow
I solved this. Note for all those who came here by google: This is not a good practice for removing workflows, but only a solution if you already messed up your workflows in SharePoint. (like me)
$oldWorkflow="MyOldWorkflow";
foreach ($item in $list.Items) {
foreach ($wf in $item.Workflows) {
if ($wf.ParentAssociation.Name -eq $oldWorkflow) {
Write-Host ("[{0}] Workflow '{1}' will be removed" -f $item.Title, $wf.ParentAssociation.Name);
$itemsToAdd.Add($wf);
}
}
}
ForEach($item in $itemsToAdd) {
$man.RemoveWorkflowFromListItem($item);
}
Related
I'm working on an App for Office that inserts text/images into specific parts of the current Word document, as far as I've investigated, the only way to achieve this is by using ContentControls and creating a binding with:
Office.context.document.bindings.addFromNamedItemAsync();
Now, the problem is that when I have Content Controls inside both, the document body and the header/footer, I'm getting the following error:
Code: 3007
Name: Binding Creation Error
Message: Multiple objects with the same name were found.
According to Microsoft's website!, this is due to 2 or more CCs with the same name; but this is not the case since every CC that I created has an unique name, and when I move all of them to either the header/footer or the body, it works, the error just happens when they are located in different sections of the document.
This is the code I'm using:
Office.context.document.bindings.addFromNamedItemAsync("HeaderLogoCC","text",
{ id: 'logoBinding' }, function (result)
{
if (result.status == "failed")
{
result.error.message == "The named item does not exist."
}
(I know my English is not the best, I apologize in advance for any mistake and I can try to make it more clear, if necessary).
Any help would be really appreciated,
Thanks!
I'm writing a script to copy items from one list to another on a sharepoint online server. I'm using the 2013 sharepoint Client Side Object Model (CSOM) to script this in powershell ISE. This should be an easy task, but it's proving just the opposite. So far I can retreive all the items using camlquery and I'm just trying to duplicate those items and their attachments to another list. The error I receive is from trying to establish an attachmentCollection to retrieve all of the attachments from any item, here is a portion of the script that represents the problem:
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"
$siteURL = "https://mysite.sharepoint.com"
$password = Read-Host -Prompt "Enter Password" -AsSecureString
$ctx = New-Object Microsoft.Sharepoint.Client.ClientContext($siteURL)
$credentials = New-Object Microsoft.Sharepoint.Client.SharepointOnlineCredentials("admin#mysite.sharepoint.com", $password)
$ctx.Credentials = $credentials
#...Bunch of code that establishes/loads web/lists/items, all works fine
function CopyItem $itemToCopy
function CopyItem ($oldItem)
{
Write-Host "Copying item" $oldItem.ID
$newItemCI = New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
$newItem = $archList.AddItem($newItemCI)
$ctx.load($newItem)
#Update fields
$ctx.load($sourceList.Fields)
$ctx.ExecuteQuery()
foreach($field in $sourceList.Fields)
{
$newItem[$field.InternalName] = $oldItem[$field.InternalName]
}
$attachments = New-Object Microsoft.SharePoint.Client.AttachmentCollection #ERROR HERE
$attachments = $oldItem.AttachmentFiles
$ctx.load($attachments)
$newItem.AttachmentFiles.Add($attachments)
$newItem.Update()
$ctx.load($newItem)
$ctx.ExecuteQuery()
}
The error message says: "The List Archive Failed at: with this error message: Constructor not found. Cannot find an appropriate constructor for type Microsoft.SharePoint.Client.AttachmentCollection."
I get the same error if I try to create new-object as Attachment as well, can't find constructor. This is odd, as the constructor should be in the client.dll, but no luck. I've even tried repairing my 2013 CSOM files, no errors were found there. Any help on this is appreciated, thank you.
After a hellish amount of trial and error, I discovered that you did not need to declare a new-object when dealing with the attachmentCollection objects. You can simply set a variable up like so:
$attachments = $item.AttachmentFiles
$attachments is now an array of attachment objects.
However, there is still a huge issue of copying/adding attachments to new items, since sharepoint has a horrible system for managing these attachments and does not initially have a folder to store them, nor can you create a folder directly. I'm still having trouble copying attachments between items, if anyone has knowledge of how to accomplish this, I would love help on that as well.
The main problem in adding attachments to AttachmentFiles property is that it uses the $item.AttachmentFiles.Add() method, which requires the parameter to be a AttachmentCreationInformation Object, not an attachment Object. I have no idea how to make this function as I intend so that I can add a pre-existing attachment to a new item.
this is some code I wrote:
Add-PSSnapin Microsoft.SharePoint.PowerShell
$webURL = "http://nycs00058260/sites/usitp"
$lists = "OsEM1","OsEM2","OsEM3","OsEM4"
$web = Get-SPWeb -Identity "http://nycs00058260/sites/usitp"
foreach($list in $lists)
... ...
Write-Host $item["Title"]
#$item["Item"]=$item["Title"] +" ,"+$webURL+"\"+$filename
$item["Item"]="$tmpValue"+" ,$item[Title]"
$item.Update()
}
}
}
it said: Unable to index into an object of type MicroSoft.SharePoint.SPListItem.
something worong when I change the $item["Item"] value?
There are a few reasons that cause this behavior:
Your permissions don't match what you need to change an item. If you have PowerShell rights, this is often not the case.
Your list is somehow corrupted. This could have something to do with site columns, content types, the list itself, or views. If you created and did not update the list schema (definition), it wouldn't let you edit it.
You don't have AllowUnsafeUpdates set to on for the SPWeb (site) object.
All three of these issues generally have better (matching) error messages but sometimes SharePoint doesn't give you all the information that you need in the error messages.
If you need more details, please ask.
I am trying to host a long running workflow service on Azure but I am having problems with correlation.
I have got the timeToUnload and the timeToPersist set to 0 and I have ticked the "persist before send" in the worklow - this is not a problem with persistence, it is to do with how instance keys are calculated.
When one web server starts a workflow and another then tries to take another action on the workflow, it fails with
System.ServiceModel.FaultException: The execution of an InstancePersistenceCommand was
interrupted because the instance key '12e0b449-7a71-812d-977a-ab89864a272f' was not
associated to an instance. This can occur because the instance or key has been cleaned up,
or because the key is invalid. The key may be invalid if the message it was generated from
was sent at the wrong time or contained incorrect correlation data.
I used the wcf service diagnostic to dig into this and I found that it is because the calculation of the instance key includes the website instance name, thus a given workflow instance can only be called back from the same machine that instantiated it (because Azure set a different website instance name on each role instance).
To explain, when I create a new instance of the workflow, I have an activity that gets the workflow instance Guid and then returns that guid and also uses the correlation initializer to set the correlation handle.
I have enabled Service Tracing in web.config so in the Service Trace Viewer I can see the following happening when I instantiate a new instance of the workflow;
<ApplicationData >
<TraceData >
<DataItem >
<TraceRecord Severity ="Information" Channel="Analytic " xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord ">
<TraceIdentifier >225</ TraceIdentifier>
<Description >Calculated correlation key '496e3207-fe9d-919f-b1df-f329c5a64934' using values 'key1:10013d62-286e-4a8f-aeb2-70582591cd7f,' in parent scope '{/NewOrbit.ExVerifier.Web_IN_2_Web/Workflow/Application/}Application_default1.xamlx'.</Description >
<AppDomain >/LM/W3SVC/1273337584/ROOT-1-129811251826070757</AppDomain >
</TraceRecord >
</DataItem >
</TraceData >
</ApplicationData >
The important line is this:
Calculated correlation key '496e3207-fe9d-919f-b1df-f329c5a64934' using values 'key1:10013d62-286e-4a8f-aeb2-70582591cd7f,' in parent scope '{/NewOrbit.ExVerifier.Web_IN_2_Web/Workflow/Application/}Application_default1.xamlx'.
The Guid of this particular workflow instance is 10013d62-286e-4a8f-aeb2-70582591cd7f so the workflow engine calculates an "instance key" from that which is 496e3207-fe9d-919f-b1df-f329c5a64934.
I can see the workflow instance with the guid in [System.Activities.DurableInstancing].[InstancesTable] and I can see the instance key in [System.Activities.DurableInstancing].[KeysTable].
So far, so good and if the same server makes a later call to that same workflow, everything works fine. However, if a different server tries to access the workflow, I get the correlation error mentioned above. Once again looking at the diagnostics trace, I can see this:
<TraceData >
<DataItem >
<TraceRecord Severity ="Information" Channel="Analytic " xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord ">
<TraceIdentifier >225</ TraceIdentifier>
<Description >Calculated correlation key '12e0b449-7a71-812d-977a-ab89864a272f' using values 'key1:10013d62-286e-4a8f-aeb2-70582591cd7f,' in parent scope '{/NewOrbit.ExVerifier.Web_IN_5_Web/Workflow/Application/}Application_default1.xamlx'. </Description >
<AppDomain >/LM/W3SVC/1273337584/ROOT-1-129811251818669004</AppDomain >
</TraceRecord >
</DataItem >
</TraceData >
The important line is
Calculated correlation key '12e0b449-7a71-812d-977a-ab89864a272f' using values 'key1:10013d62-286e-4a8f-aeb2-70582591cd7f,' in parent scope '{/NewOrbit.ExVerifier.Web_IN_5_Web/Workflow/Application/}Application_default1.xamlx'.
As you can see, it is the same Guid being passed in but the system includes the name of the website instance in the calculation of the Instance key so it ends up with a completely different instance key.
I have created a completely new project to test this out and found the exact same problem. I feel I must be doing something very simple wrong as I can't find anyone else with the same problem.
A few months later and I have found a solution to this problem. The root problem is that Azure names the Web site something different on each role instance; Rather than "Default Web SIte", the web site is called something like NewOrbit.ExVerifier.Web_IN_0_Web (given a namespace for your web project of NewOrbit.ExVerifier.Web). Workflow uses the website name as part of the algorithm used to calculate the instance key, hence the problem.
The solution is, quite simply, to rename the website during role startup so it is called the same thing on all instances. Fixing the root problem rather than handling the consequences and so obvious I never saw it the first time round.
Here is how you can do this (losely based on this: http://blogs.msdn.com/b/tomholl/archive/2011/06/28/hosting-services-with-was-and-iis-on-windows-azure.aspx)
Configure powershell to have elevated access rights so you can make changes after IIS has been configured:
In ServiceDefinition.csdef add a startup task:
<ServiceDefinition name="WasInAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole1">
...
<Startup>
<Task commandLine="setup\startup.cmd" executionContext="elevated" />
</Startup>
</WebRole>
</ServiceDefinition>
Setup\Startup.cmd should have this content:
powershell -command "set-executionpolicy Unrestricted" >> out.txt
Configure Role OnStart to have admin priviliges
In ServiceDefinition.csdef add this:
<ServiceDefinition name="WasInAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
<WebRole name="WebRole1">
...
<Runtime executionContext="elevated" />
</WebRole>
</ServiceDefinition>
Create a powershell script to rename the web site
Create a setup\RoleStart.ps1 file:
write-host "Begin RoleStart.ps1"
import-module WebAdministration
$siteName = "*" + $args[0] + "*"
Get-WebSite $siteName | Foreach-Object {
$site = $_;
$siteref = "IIS:/Sites/" + $site.Name;
try {
Rename-Item $siteref 'MyWebSite'
write-host $siteName + " was renamed"
}
catch
{
write-host "Failed to rename " + $siteName + " : " + $error[0]
}
}
write-host "End RoleStart.ps1"
(replace MyWebSite with whatever you want the website to be called on all the servers).
Run RoleStart.ps1 on role start:
Create or Edit WebRole.cs in the root of your website project and add this code:
public class WebRole : RoleEntryPoint
{
public override bool OnStart()
{
var startInfo = new ProcessStartInfo()
{
FileName = "powershell.exe",
Arguments = #".\setup\rolestart.ps1",
RedirectStandardOutput = true,
UseShellExecute=false,
};
var writer = new StreamWriter("out.txt");
var process = Process.Start(startInfo);
process.WaitForExit();
writer.Write(process.StandardOutput.ReadToEnd());
writer.Close();
return base.OnStart();
}
}
And that should be it. If you spin up multiple web role instances and connect to them with RDP, you should now be able to see that the website is called the same on all the instances and workflow persistence therefore works.
It appears this is a problem with running workflow services in a web role. Looks like the workaround is to run you workflow services in a worker role which doesn't have the same problem.
I’m not familiar with Workflow persistence. But others have reported they’ve successfully made SQL Azure work with WF persistence, I would like to suggest you to check http://social.msdn.microsoft.com/Forums/en-US/ssdsgetstarted/thread/2dac9194-0067-4e16-8e95-c15a72cb0069/ and http://www.theworkflowelement.com/2011/05/wf-persistence-on-sql-azure.html to see if they help.
Best Regards,
Ming Xu.
We are new to WF and WCF but was wondering if you could build your own Instance Store.
This should give you the ability to override InstanceKey whereby you could calculate your own.
There are quite a few examples on the internet.
After decompiling and searching a lot, I finnaly found where the key is Generated.
In the class System.ServiceModel.Channels.CorrelationKey, System.ServiceModel
The method GenerateKeyString does the trick. Now I have to find a way to override this method and make my own generating key algorithm so the same instance can run in multiple web servers with different names.
private static Guid GenerateKey(string keyString)
{
return new Guid(HashHelper.ComputeHash(Encoding.Unicode.GetBytes(keyString)));
}
private static string GenerateKeyString(ReadOnlyDictionaryInternal<string, string> keyData, string scopeName, string provider)
{
if (string.IsNullOrEmpty(scopeName))
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("scopeName", System.ServiceModel.SR.GetString("ScopeNameMustBeSpecified"));
if (provider.Length == 0)
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("provider", System.ServiceModel.SR.GetString("ProviderCannotBeEmptyString"));
StringBuilder stringBuilder1 = new StringBuilder();
StringBuilder stringBuilder2 = new StringBuilder();
SortedList<string, string> sortedList = new SortedList<string, string>((IDictionary<string, string>) keyData, (IComparer<string>) StringComparer.Ordinal);
stringBuilder2.Append(sortedList.Count.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo));
stringBuilder2.Append('.');
for (int index = 0; index < sortedList.Count; ++index)
{
if (index > 0)
stringBuilder1.Append('&');
stringBuilder1.Append(sortedList.Keys[index]);
stringBuilder1.Append('=');
stringBuilder1.Append(sortedList.Values[index]);
stringBuilder2.Append(sortedList.Keys[index].Length.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo));
stringBuilder2.Append('.');
stringBuilder2.Append(sortedList.Values[index].Length.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo));
stringBuilder2.Append('.');
}
if (sortedList.Count > 0)
stringBuilder1.Append(',');
stringBuilder1.Append(scopeName);
stringBuilder1.Append(',');
stringBuilder1.Append(provider);
stringBuilder2.Append(scopeName.Length.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo));
stringBuilder2.Append('.');
stringBuilder2.Append(provider.Length.ToString((IFormatProvider) NumberFormatInfo.InvariantInfo));
stringBuilder1.Append('|');
stringBuilder1.Append((object) stringBuilder2);
return ((object) stringBuilder1).ToString();
}
I am trying to sync Sharepoint task list with Outlook. When the users connect the task list to outlook, the task for all users are visible in outlook. Rather than applying filtering in Outlook, can I provide a filtering at the source itself? There are considerable number of users for my application, it wouldn't be good to ask all users to apply filters on their own.
Any other suggestions?
Thanks.
I`v asked the same question: Sync list with outlook only with items in current view.. In this case it was possible to use stssync protocol to do whatever you want. It takes much effort (luckily someone already wrote an implementation)
But there was another solution i ended up using - implementing a wrapper for Lists.asmx webservice and rewriting outlook requests (by using custom Global.asax file) to use this new webservice instead of Lists.asmx, that only queries specific view in a list.
if (ctx.Request.UserAgent.Contains("Microsoft Office Outlook") && path.ToLower().IndexOf("_vti_bin/lists.asmx") >= 0)
{
ctx.RewritePath("/_layouts/OutlookLists.asmx");
}
I'm not sure you would want a solution like this. If you do, you may ask and i may publish the solution source for the webservice, however i'm not using this webservice myself anymore. And you could use it as a draft, not a production ready code.
The source has been published on CodePlex.
Regarding to the script problem
I don't know why list id isn't being replaced by view id. I tried to run the function within script console (F12 for IE8/9)
>> var menuItems = document.getElementsByTagName('ie:menuitem');
for (var i = 0; i < menuItems.length; i++) {
itm = menuItems(i);
if (itm.id.match('OfflineButton') != null) {
console.log('listName:' + ctx.listName.toLowerCase() + 'viewName:' + ctx.view.toLowerCase());
if (ctx != null && ctx.listName != null && ctx.view != null) {
console.log('Inside if block');
//Replace listId to viewId being used so outlook will query only items in current view.
//Must have custom web service in place to handle that request, because it iwll not work OOTB.
console.log("Before: " + itm.onMenuClick);
itm.onMenuClick = itm.onMenuClick.replace(ctx.listName.toLowerCase(), ctx.view.toLowerCase());
console.log("After: " + itm.onMenuClick);
break;
}
}
}
LOG: listName:{fe89e809-7de4-4f43-9bc2-7e8ce6624ed0}viewName:{7364a843-c7f2-47d8-b4a3-5dc7381b6248}
LOG: Inside if block
LOG: Before: javaScript:ExportHailStorm('tasks','https:\u002f\u002fserver\u002fsapulces\u002fdarbu_parskata','{fe89e809-7de4-4f43-9bc2-7e8ce6624ed0}','Uz\u0146\u0113muma darbu p\u0101rskata sapulce','Uzdevumi','\u002fsapulces\u002fdarbu_parskata\u002fLists\u002fUzdevumi','','\u002fsapulces\u002fdarbu_parskata\u002fLists\u002fUzdevumi');
LOG: After: javaScript:ExportHailStorm('tasks','https:\u002f\u002fserver\u002fsapulces\u002fdarbu_parskata','{7364a843-c7f2-47d8-b4a3-5dc7381b6248}','Uz\u0146\u0113muma darbu p\u0101rskata sapulce','Uzdevumi','\u002fsapulces\u002fdarbu_parskata\u002fLists\u002fUzdevumi','','\u002fsapulces\u002fdarbu_parskata\u002fLists\u002fUzdevumi');
As you can see, the function argument (third one) has been replaced with a view id instead of list id.
Don't forget to remove console.log statements before deploying, because if IE doesn't have web developer tools, javascript will crash there.
Were these tasks created from a workflow? this is a known issue with SharePoint 2007.
http://social.technet.microsoft.com/Forums/en/sharepointadmin/thread/64b3b124-085c-4d8e-8e85-8bd20736e0e7
http://blah.winsmarts.com/2007-4-SharePoint_2007__Fine_grained_permission_control.aspx
You could try setting the read/edit permissions to "only their own", but i think that breaks approval/alerts from working
I believe the problem is fixed in SharePoint 2010, i think tasks get created with fine-grained permissions per task.