Does anyone know how to customize the master page (i.e. default.master) for a WSS 3.0 site? Actually, I already know how to customize the master page (i.e. via SharePoint Designer, or a text editor), I'm more interested in learning how to tell WSS 3.0 to use my customized master page.
I've renamed the default.master with my customized version and that works, but that sets it for all WSS sites. I want to be able to use version A of a master page for site collection A, and a separate master page for other site collections.
Note, I'm NOT referring to MOSS 2007. I already know how to set the master page for MOSS 2007. I can't seem to figure out how to do it for WSS 3.0 though.
Thanks.
WSS pages use Master Pages just like regular web apps. However, the value if the MasterPageFile attribute is a token, and is set to "~default.master". This token gets replaced with the actual reference to the master page in the page's PreInit method.
You can change the value of ~default.master to anything you like. But a better solution is to do the same type of thing that SharePoint does.
I added an HttpHandler to my SharePoint site. The handler attaches to the PreRequestHandlerExecute method, and changes the value of the master page file attribute before SharePoint starts rendering the page.
Add a line to the httpModules section of the web.config that looks like this:
Then create a class like this:
namespace MyClassLibrary.Utility
{
public class MasterPageHttpModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
}
void context_PreRequestHandlerExecute(object sender, EventArgs e)
{
bool useCustomMasterPages = Convert.ToBoolean(ConfigurationManager.AppSettings["ShowCustomMasterPages"].ToString());
if (useCustomMasterPages)
{
Page page = HttpContext.Current.CurrentHandler as Page;
if (page != null)
{
page.PreInit += new EventHandler(page_PreInit);
}
}
}
void page_PreInit(object sender, EventArgs e)
{
bool useThreeColumnMaster = Convert.ToBoolean(ConfigurationManager.AppSettings["UseThreeColumnMasterOnDefaultPage"].ToString());
try
{
Page page = sender as Page;
if (page != null && SPContext.Current != null)
{
string url = page.Request.Url.AbsolutePath.ToLower();
if (url.IndexOf("/public/") > -1)
{
if (url.IndexOf("sitemap.aspx") == -1)
{
page.MasterPageFile = "~/_catalogs/masterpage/edge_con.master";
}
else
{
page.MasterPageFile = "";
}
}
else if (url.IndexOf("default.aspx") > -1)
{
if (useThreeColumnMaster)
{
page.MasterPageFile = "~/_catalogs/masterpage/edge_con.master";
}
else
{
page.MasterPageFile = "~/_catalogs/masterpage/edge.master";
}
}
else if (url.IndexOf("sitemap.aspx") > -1)
{
//
// Sitemap pages should not have a master page
//
page.MasterPageFile = "";
page.Controls.Clear();
}
else if (url.IndexOf("/admin/") > -1)
{
page.MasterPageFile = "~/_catalogs/masterpage/edge.master";
}
else if (url.IndexOf("/member/") > -1)
{
page.MasterPageFile = "~/_catalogs/masterpage/edge.master";
}
else if (url.IndexOf("/supplier/") > -1)
{
page.MasterPageFile = "~/_catalogs/masterpage/edge.master";
}
else if (page.MasterPageFile == "~masterurl/default.master")
{
page.MasterPageFile = "~/_catalogs/masterpage/edge.master";
}
}
}
catch (Exception exception)
{
LogWriter logWriter = new LogWriter();
logWriter.WriteToLog("Could not set master page: " + exception.Message, LogType.MasterPage, DateTime.Now);
}
}
public void Dispose()
{
}
}
}
Now you are dynamically choosing a mater page.
You need to change the MasterUrl property on the SPWeb object representing the site. A good way to do this is to create a SharePoint feature that when activated sets the property, and when deactivated restores the original value. The Feature.xml could look like this:
<?xml version="1.0" encoding="utf-8"?>
<Feature Id="8651CC66-FEB1-4255-B7E9-0DFE24367DAB"
Title="My Master Page"
Scope="Web"
SolutionId="06D3B01F-0C26-457a-BFA5-A1B0BC8D4225"
ReceiverAssembly="MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9e95445247029289"
ReceiverClass="MyFeatureReceiver"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="Masterpage.xml"/>
<ElementFile Location="my.master"/>
</ElementManifests>
<Properties>
<Property Key="MyMaster" Value="my.master" />
</Properties>
</Feature>
The file Masterpage.xml uploads your master page to the gallery:
<?xml version="1.0" encoding="utf-8" ?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="UploadMaster" Url="_catalogs/masterpage" >
<File Url="my.master" Type="GhostableInLibrary" IgnoreIfAlreadyExists="True"/>
</Module>
</Elements>
Include this feature in a WSP solution along with the MyAssembly.dll containing the MyFeatureReceiver class, which goes like this:
public class MyFeatureReceiver : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb web = (SPWeb)properties.Feature.Parent;
web.MasterUrl = properties.Definition.Properties["MyMaster"].Value;
web.Update();
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
SPWeb web = (SPWeb)properties.Feature.Parent;
web.MasterUrl = "default.master";
web.Update();
}
public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{
}
public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
{
}
}
Finally, deploy the solution and activate the feature on your site(s).
Related
This is the way I save a property of my webpart in a farm solution:
SPContext.Current.Web.AllowUnsafeUpdates = true;
SPFile file = SPContext.Current.File;
SPLimitedWebPartManager mgr = file.GetLimitedWebPartManager(PersonalizationScope.Shared);
for (int index = 0; index < mgr.WebParts.Count; index++)
{
if (mgr.WebParts[index].ID == this.ID)
{
((MyWebpartType) mgr.WebParts[index]).MyStringProperty = "Hello World!";
mgr.SaveChanges(mgr.WebParts[index]);
}
}
SPContext.Current.Web.AllowUnsafeUpdates = false;
Works fine.
Now I have to achieve the same but in a sandbox solution but there is no SPLimitedWebPartManager available.
So how can I change a webpart property by code inside a sandbox solution webpart?
Found the solution, a call to SetPersonalizationDirty() in the webpart saves all properties.
You may define your own custom webpart property as below:
public partial class BannerSlider : System.Web.UI.WebControls.WebParts.WebPart
{
[WebBrowsable(true),
Personalizable(PersonalizationScope.Shared),
WebDescription("My WebPart Property"),
Category("Custom Properties"),
WebDisplayName("My WebPart Property")]
public string MyProperty
{
get { return __myProperty; }
set { _myProperty= value; }
}
protected void Page_Load(object sender, EventArgs e)
{
this.MyProperty = "Hello World";
I am trying to create a custom workflow activity which gives me the list of recipients that I am storing in list. But once I deploy and start the workflow nothing is happening, not even log messages are coming. So i tried to debug the code but breakpoints are not set and I am getting the error "The Breakpoint will not currently be hit. No symbols have been loaded for this document." Can anyone please help me to deal with this issue.
Below are the steps I have followed in creating this activity.
1. created a workflow activity library.
(please find my code file attached)
added .dll to GAC
updated web.config and WSS.actions files.
Now I see the action in designer, so i have created a workflow using designer.
strted the workflow manually on an item.
Here nothing is happening, not even an error. Please let me know if you need any further information.
Please find the code below.
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using System.Diagnostics;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;
namespace CustomWorkflowActivityLibrary
{
public partial class CustomWorkflowActivity: SequenceActivity
{
SPList _list;
private EventLog _log;
SPFieldUserValueCollection objUserFieldValueCol;
string semailsettingKeyword1;
string semailsettingKeyword2;
public CustomWorkflowActivity()
{
InitializeComponent();
}
public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(CustomWorkflowActivity));
[DescriptionAttribute("__Context")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get { return ((WorkflowContext)(base.GetValue(CustomWorkflowActivity.__ContextProperty))); }
set { base.SetValue(CustomWorkflowActivity.__ContextProperty, value); }
}
public static DependencyProperty ListIdProperty = DependencyProperty.Register("ListId", typeof(string), typeof(CustomWorkflowActivity));
[DescriptionAttribute("ListId")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public string ListId
{
get { return ((string)(base.GetValue(CustomWorkflowActivity.ListIdProperty))); }
set { base.SetValue(CustomWorkflowActivity.ListIdProperty, value); }
}
public static DependencyProperty ListItemProperty = DependencyProperty.Register("ListItem", typeof(int), typeof(CustomWorkflowActivity));
[DescriptionAttribute("ListItem")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public int ListItem
{
get { return ((int)(base.GetValue(CustomWorkflowActivity.ListItemProperty))); }
set { base.SetValue(CustomWorkflowActivity.ListItemProperty, value); }
}
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
_log = new EventLog("Add Description");
_log.Source = "Share Point Workflows";
try
{
//Execute method as a elevated method
SPSecurity.CodeToRunElevated elevatedExecuteMethod = new SPSecurity.CodeToRunElevated(ExecuteMethod);
SPSecurity.RunWithElevatedPrivileges(elevatedExecuteMethod);
}
catch (Exception ex)
{
_log.WriteEntry("Error" + ex.Message.ToString(), EventLogEntryType.Error);
}
return ActivityExecutionStatus.Closed;
}
private void ExecuteMethod()
{
try
{
//retrieveing the Site object
SPSite _site = new SPSite(__Context.Site.Url);
//retrieveing the Web object
SPWeb _web = (SPWeb)(__Context.Web);
//retrieveing the list object
_list = _web.Lists[new Guid(this.ListId)];
//retrieveing the list item object
SPListItem _listItem = _list.GetItemById(this.ListItem);
_site.AllowUnsafeUpdates = true;
_web.AllowUnsafeUpdates = true;
string semailsubject = _listItem["E-Mail Subject"].ToString();
string semailfrom = _listItem["emailfrom"].ToString();
_log = new EventLog("get vendor info");
_log.WriteEntry("semailsubject");
_log.WriteEntry("semailfrom");
/* _listItem.Update();
_list.Update();
_site.AllowUnsafeUpdates = false;
_web.AllowUnsafeUpdates = false;*/
using (SPSite mysite = new SPSite("http://dlglobaltest.dl.com/Admin/IT/Application%20Development%20Group/LibraryEmailDistribution"))
{
using (SPWeb myweb = mysite.OpenWeb())
{
SPList settingsList = myweb.Lists["EmailDistributionSettings"];
SPQuery oQuery = new SPQuery();
oQuery.Query = "<Where><Eq><FieldRef Name='Sender' /><Value Type='Text'>" + semailfrom + "</Value></Eq></Where>";
SPListItemCollection ColListItems = settingsList.GetItems(oQuery);
foreach (SPListItem oListItem in ColListItems)
{
semailsettingKeyword1 = oListItem["Keyword1"].ToString();
semailsettingKeyword2 = oListItem["Keyword2"].ToString();
//SPFieldUserValue objUserFieldValue = new SPFieldUserValue(myweb, oListItem["Recipients"].ToString());
if ((semailsubject.Contains(semailsettingKeyword1)) || (semailsubject.Contains(semailsettingKeyword2)))
{
objUserFieldValueCol = new SPFieldUserValueCollection(myweb, oListItem["Recipients"].ToString());
_log = new EventLog(objUserFieldValueCol.ToString());
}
}
}
}
}
catch (Exception ex)
{ }
}
}
}
Web.Config:
<authorizedType Assembly="CustomWorkflowActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a95e146fc1062337" Namespace="CustomWorkflowActivityLibrary" TypeName="*" Authorized="True" />
WSS.Actions:
<Action Name="Get Recipients"
ClassName="CustomWorkflowActivityLibrary.CustomWorkflowActivity"
Assembly="CustomWorkflowActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a95e146fc1062337"
AppliesTo="all" Category="Custom">
<RuleDesigner Sentence="Get Recipients for %1 ">
<FieldBind Field="ListId,ListItem" Text="this list" Id="1" DesignerType="ChooseListItem" />
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
<Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In" />
</Parameters>
</Action>
Thanks,
I am not sure if this will help but you could try changing the following line in your code from this:
SPSecurity.RunWithElevatedPrivileges(elevatedExecuteMethod);
To this:
SPSecurity.RunWithElevatedPrivileges(delegate(){
ExecuteMethod();
});
Another shot-in-the-dark reply:
Try changing the class you're inheriting ( http://msdn.microsoft.com/en-us/library/ms173149(v=VS.80).aspx ) from SequenceActivity to Activity (SequenceActivity inherits from CompositeActivity, which itself inherits from Activity. See: http://msdn.microsoft.com/en-us/library/system.workflow.activities.sequenceactivity(v=VS.90).aspx )
If that doesn't work, try removing your constructor entirely. You should be able to use the base (Sequence)Activity constructor (since you're inheriting the class, not implementing it)
Hope that helps...
How do I add the out-of-the-box SharePoint date filter webpart to an ASP.Net web page?
I want to do it either in an ASPX...
<%# Register Assembly="<DateFilterDLL??>" Namespace="<??>" TagPrefix="DP" %>
<...>
<asp:WebPartManager ID="WebPartManager1" runat="server">
</asp:WebPartManager>
<...>
<ZoneTemplate>
<DP:<DateFilterWebPart??> ID="DateFilter" runat="server" />
or programmatically, in the ASPX.CS
protected void Page_Load(object sender, EventArgs e)
{
this.Controls.Add(<Microsoft.Something.DatePicker??>
}
In your code behind add a reference to Microsoft.Sharepoint and Microsoft.Sharepoint.WebControls
Then declare DateTimeControl dtc;
In your page Load or Page Init just use
dtc=new DateTimeControl();
this.Controls.Add(dtc);
This should add the datecontrol. Let me know if u face some issue
It will be easier to use standard SharePoint DateTimeControl.
Here is a common method for this with DateTimeControl, hope it will help someone with the same issue.
/// <summary>
/// Get common SP DateTimeControl with current DateOnly settings and MethodToProcessDateChanged
/// </summary>
public static DateTimeControl Cd(this bool DateOnly, bool AutoPostBack = false,
DateTime? SelectedDate = null, Func<bool> MethodToProcessDateChanged = null)
{
var d = new DateTimeControl();
d.DateOnly = DateOnly;
d.AutoPostBack = AutoPostBack;
if (SelectedDate != null)
d.SelectedDate = SelectedDate.Value;
if (MethodToProcessDateChanged != null)
d.DateChanged += (o, e) => { MethodToProcessDateChanged();};
return d;
}
See more details on how to use it here
As the question says - is there a way to determine which pages are including my web part?
If you're looking for code, I've got something for you. If you'd like to find all Content Query web parts then you would call my code like this:
FindWebPart("http://server.com/", "Microsoft.SharePoint.Publishing.WebControls.ContentByQueryWebPart");
Here's the code:
public static void FindWebPart(string siteCollectionUrl, string webPartName)
{
using (SPSite siteCollection = new SPSite(siteCollectionUrl))
{
using (SPWeb rootSite = siteCollection.OpenWeb())
{
FindWebPartHelper(rootSite, webPartName);
}
}
}
public static void FindWebPartHelper(SPWeb site, string webPartName)
{
// Search for web part in Pages document library
SPList pagesList = null;
try
{
pagesList = site.Lists["Pages"];
}
catch (ArgumentException)
{
// List not found
}
if (null != pagesList)
{
SPListItemCollection pages = pagesList.Items;
foreach (SPListItem page in pages)
{
SPFile file = page.File;
using (SPLimitedWebPartManager mgr = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
try
{
SPLimitedWebPartCollection webparts = mgr.WebParts;
foreach (System.Web.UI.WebControls.WebParts.WebPart wp in webparts)
{
// Here perform the webpart check
// For instance you could identify the web part by
// its class name
if (webPartName == wp.GetType().ToString())
{
// Found a match! Now do something...
Console.WriteLine("Found web part!");
}
}
}
finally
{
// Needs to be disposed
mgr.Web.Dispose();
}
}
}
}
// Check sub sites
SPWebCollection subSites = site.Webs;
foreach (SPWeb subSite in subSites)
{
try
{
FindWebPartHelper(subSite, webPartName);
}
finally
{
// Don't forget to dispose!
subSite.Dispose();
}
}
}
Ofcourse you can make little changes to this code. Currently it does a string comparison, but it's easy to do it in a more typed way. Have fun!
By way of an alternative, if you want to test web part pages including the default page on collaboration sites, you can use the following code snippet which uses the Files property of the SPWeb object:
private static void FindWebPart(string siteUrl, string webPartName)
{
using (var site = new SPSite(siteUrl))
{
foreach (SPWeb web in site.AllWebs)
{
foreach (var file in web.Files.Cast<SPFile>().Where(file => file.Name.EndsWith("aspx")))
{
FindWebPartOnPage(webPartName, file);
}
var pagesTemplateType = (SPListTemplateType)Enum.Parse(typeof(SPListTemplateType), "850");
foreach (var documentLibrary in web.Lists.Cast<SPList>().Where(list => list.BaseTemplate == pagesTemplateType || (list.BaseTemplate == SPListTemplateType.DocumentLibrary && list.Title.Contains("Pages"))))
{
foreach (var file in documentLibrary.Items.Cast<SPListItem>().Where(item => item.File.Name.EndsWith("aspx")).Select(item => item.File))
{
FindWebPartOnPage(webPartName, file);
}
}
web.Dispose();
}
}
}
private static void FindWebPartOnPage(string webPartName, SPFile file)
{
using (var webPartManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
if (webPartManager.WebParts.Cast<WebPart>().Any(webPart => webPart.GetType().Name == webPartName))
{
Console.WriteLine(file.ServerRelativeUrl);
}
webPartManager.Web.Dispose();
}
}
Note: the Pages library created by the Publishing feature does not have a BaseTemplate value of SPListTemplateType.DocumentLibrary; instead it is represented by a "hidden" value of 850.
This is called a similar manner to LeonZandman's answer, however only the class name is used to supply a match:
FindWebPart("http://yoursite.com/", "MyWebPart");
In Sharepoint designer's workflow editor I wish to retrieve the username/name of the work flow initiator (i.e. who kicked it off or triggered the workflow) - this is relatively easy to do using 3rd party products such as Nintex Workflow 2007 (where I would use something like {Common:Initiator}) - but I can't seem to find any way out of the box to do this using share point designer and MOSS 2007.
Update
It does not look like this rather obvious feature is supported OOTB, so I ended up writing a custom activity (as suggested by one of the answers). I have listed the activities code here for reference though I suspect there are probably a few instances of this floating around out there on blogs as it's a pretty trivial solution:
public partial class LookupInitiatorInfo : Activity
{
public static DependencyProperty __ActivationPropertiesProperty =
DependencyProperty.Register("__ActivationProperties",
typeof(Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties),
typeof(LookupInitiatorInfo));
public static DependencyProperty __ContextProperty =
DependencyProperty.Register("__Context", typeof (WorkflowContext),
typeof (LookupInitiatorInfo));
public static DependencyProperty PropertyValueVariableProperty =
DependencyProperty.Register("PropertyValueVariable", typeof (string),
typeof(LookupInitiatorInfo));
public static DependencyProperty UserPropertyProperty =
DependencyProperty.Register("UserProperty", typeof (string),
typeof (LookupInitiatorInfo));
public LookupInitiatorInfo()
{
InitializeComponent();
}
[Description("ActivationProperties")]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties __ActivationProperties
{
get { return ((Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties)(base.GetValue(__ActivationPropertiesProperty))); }
set { base.SetValue(__ActivationPropertiesProperty, value); }
}
[Description("Context")]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public WorkflowContext __Context
{
get { return ((WorkflowContext)(base.GetValue(__ContextProperty))); }
set { base.SetValue(__ContextProperty, value); }
}
[Description("UserProperty")]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string UserProperty
{
get { return ((string) (base.GetValue(UserPropertyProperty))); }
set { base.SetValue(UserPropertyProperty, value); }
}
[Description("PropertyValueVariable")]
[ValidationOption(ValidationOption.Required)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string PropertyValueVariable
{
get { return ((string) (base.GetValue(PropertyValueVariableProperty))); }
set { base.SetValue(PropertyValueVariableProperty, value); }
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
// value values for the UserProperty (in most cases you
// would use LoginName or Name)
//Sid
//ID
//LoginName
//Name
//IsDomainGroup
//Email
//RawSid
//Notes
try
{
string err = string.Empty;
if (__ActivationProperties == null)
{
err = "__ActivationProperties was null";
}
else
{
SPUser user = __ActivationProperties.OriginatorUser;
if (user != null && UserProperty != null)
{
PropertyInfo property = typeof (SPUser).GetProperty(UserProperty);
if (property != null)
{
object value = property.GetValue(user, null);
PropertyValueVariable = (value != null) ? value.ToString() : "";
}
else
{
err = string.Format("no property found with the name \"{0}\"", UserProperty);
}
}
else
{
err = "__ActivationProperties.OriginatorUser was null";
}
}
if (!string.IsNullOrEmpty(err))
Common.LogExceptionToWorkflowHistory(new ArgumentOutOfRangeException(err), executionContext,
WorkflowInstanceId);
}
catch (Exception e)
{
Common.LogExceptionToWorkflowHistory(e, executionContext, WorkflowInstanceId);
}
return ActivityExecutionStatus.Closed;
}
}
And then wire it up with the following .action xml file:
<?xml version="1.0" encoding="utf-8"?>
<WorkflowInfo Language="en-us">
<Actions>
<Action Name="Lookup initiator user property"
ClassName="XXX.ActivityLibrary.LookupInitiatorInfo"
Assembly="XXX.ActivityLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=XXX"
AppliesTo="all"
Category="WormaldWorkflow Custom Actions">
<RuleDesigner Sentence="Lookup initating users property named %1 and store in %2">
<FieldBind Field="UserProperty" DesignerType="TextArea" Id="1" Text="LoginName" />
<FieldBind Field="PropertyValueVariable" DesignerType="ParameterNames" Text="variable" Id="2"/>
</RuleDesigner>
<Parameters>
<Parameter Name="__Context" Type="Microsoft.Sharepoint.WorkflowActions.WorkflowContext, Microsoft.SharePoint.WorkflowActions" Direction="In"/>
<Parameter Name="__ActivationProperties" Type="Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties, Microsoft.SharePoint" Direction="In"/>
<Parameter Name="UserProperty" Type="System.String, mscorlib" Direction="In" />
<Parameter Name="PropertyValueVariable" Type="System.String, mscorlib" Direction="Out" />
</Parameters>
</Action>
</Actions>
</WorkflowInfo>
For those that google into this article and are now using SharePoint 2010, the workflow initiator variable is now supported OOTB in SharePoint Designer.
The datasource would be "Workflow Context" and the field is, of course, "Initiator" and you can choose to return it as the "Display Name", "Email", "Login Name" or the "User ID Number"
I don't think this is possible to do in SharePoint Designer out of the box. You could probably write a custom action to get the originator, but I don't believe it is exposed through the SPD workflow interface at all.
The best you could probably do is get the user who created or modified the item in the list, but this wouldn't handle cases where the workflow was manually run.
I can think about a simple but not very sophisticated solution for this one by using just SPD. Just in workflow steps create a test item in a secondary list (probably a task list which stores the workflowId and itemId properties for refrence back) and then do a lookup in your workflow on that list to see who is the creator of that item, that value would be the current workflow initiator.
The custom activity solution only work if you are working with moss, if you only have wss 3.0 you can put one step more in your workflow and set a custom comment field with any information, this make the last modified person to change and become the same as the workflow initiator, then you can use the ModifiedBy field to make any decision that you need.