A little over a year ago I created one of my first STSADM commands, gl-setpictureurlnewpath
, which I developed in order to enable me to set the picture URL property for user profile objects to a new path as the result of the upgrade which resulted in the images going to a new library. This time I needed to do set the property but there was no existing data so the existing command I had wouldn’t work as is. I considered reworking the command to accommodate both scenarios but in the end decided to just leave the existing one alone and create a new command which I called gl-setpictureurl
.
Updating a user profile object through code is actually really simple – you just get an instance of the UserProfileManager
object and then either loop through the items in the collection or use the GetUserProfile
method to retrieve a specific UserProfile
object. Once you have the object you can edit any of the properties using simple indexer notation (userProfile["PictureURL"].Value = url
). Once you’ve updated the appropriate properties you call the Commit()
method on the user profile object.
1#if MOSS
2using System;
3using System.Collections.Specialized;
4using System.Text;
5using Lapointe.SharePoint.STSADM.Commands.SPValidators;
6using Microsoft.Office.Server;
7using Microsoft.Office.Server.UserProfiles;
8using Lapointe.SharePoint.STSADM.Commands.OperationHelpers;
9using Microsoft.SharePoint;
10using System.Net;
11
12namespace Lapointe.SharePoint.STSADM.Commands.UserProfiles
13{
14 public class SetPictureUrl : SPOperation
15 {
16 /// <summary>
17 /// Initializes a new instance of the <see cref="SetPictureUrl"/> class.
18 /// </summary>
19 public SetPictureUrl()
20 {
21 SPParamCollection parameters = new SPParamCollection();
22 parameters.Add(new SPParam("path", "p", true, null, new SPNullOrNonEmptyValidator(), "Please specify the path."));
23 parameters.Add(new SPParam("sspname", "ssp", false, null, new SPNonEmptyValidator(), "Please specify the SSP name."));
24 parameters.Add(new SPParam("username", "u", false, null, new SPNonEmptyValidator(), "Please specify the username."));
25 parameters.Add(new SPParam("overwrite", "ow"));
26 parameters.Add(new SPParam("ignoremissingdata", "ignore"));
27 parameters.Add(new SPParam("validateurl", "validate"));
28
29 StringBuilder sb = new StringBuilder();
30 sb.Append("\r\n\r\nSets the picture URL path for user profiles. The following variables may be used for dynamic replacement: \"$(username)\", \"$(domain)\", \"$(email)\", \"$(firstname)\", \"$(lastname)\", \"$(employeeid)\".\r\n\r\nParameters:");
31 sb.Append("\r\n\t-path <path to new photo (i.e., \"http://intranet/hr/EmployeePictures/$(username).jpg\") - leave blank to clear>");
32 sb.Append("\r\n\t[-sspname <name of the SSP>]");
33 sb.Append("\r\n\t[-username <DOMAIN\\name>]");
34 sb.Append("\r\n\t[-overwrite]");
35 sb.Append("\r\n\t[-ignoremissingdata]");
36 sb.Append("\r\n\t[-validateurl]");
37
38 Init(parameters, sb.ToString());
39 }
40 #region ISPStsadmCommand Members
41
42 /// <summary>
43 /// Gets the help message.
44 /// </summary>
45 /// <param name="command">The command.</param>
46 /// <returns></returns>
47 public override string GetHelpMessage(string command)
48 {
49 return HelpMessage;
50 }
51
52 /// <summary>
53 /// Runs the specified command.
54 /// </summary>
55 /// <param name="command">The command.</param>
56 /// <param name="keyValues">The key values.</param>
57 /// <param name="output">The output.</param>
58 /// <returns></returns>
59 public override int Execute(string command, StringDictionary keyValues, out string output)
60 {
61 output = string.Empty;
62 Verbose = true;
63
64 string username = null;
65
66 if (Params["username"].UserTypedIn)
67 username = Params["username"].Value;
68 string path = Params["path"].Value;
69
70 ServerContext context = ServerContext.Default;
71 if (Params["sspname"].UserTypedIn)
72 context = ServerContext.GetContext(Params["sspname"].Value);
73
74 bool overwrite = Params["overwrite"].UserTypedIn;
75 bool ignoreMissingData = Params["ignoremissingdata"].UserTypedIn;
76 bool validateUrl = Params["validateurl"].UserTypedIn;
77
78 UserProfileManager profManager = new UserProfileManager(context);
79
80 if (string.IsNullOrEmpty(username))
81 SetPictures(profManager, path, overwrite, ignoreMissingData, validateUrl);
82 else
83 SetPicture(profManager, username, path, overwrite, ignoreMissingData, validateUrl);
84
85 return OUTPUT_SUCCESS;
86 }
87
88 #endregion
89
90 /// <summary>
91 /// Sets the pictures to the specified path for all user profiles.
92 /// </summary>
93 /// <param name="profManager">The prof manager.</param>
94 /// <param name="path">The path.</param>
95 /// <param name="overwrite">if set to <c>true</c> [overwrite].</param>
96 /// <param name="ignoreMissingData">if set to <c>true</c> [ignore missing data].</param>
97 /// <param name="validateUrl">if set to <c>true</c> validate the url.</param>
98 public static void SetPictures(UserProfileManager profManager, string path, bool overwrite, bool ignoreMissingData, bool validateUrl)
99 {
100 foreach (UserProfile profile in profManager)
101 {
102 SetPicture(profile, path, overwrite, ignoreMissingData, validateUrl);
103 }
104 }
105
106 /// <summary>
107 /// Sets the picture URL for the specfied user.
108 /// </summary>
109 /// <param name="profManager">The prof manager.</param>
110 /// <param name="username">The username.</param>
111 /// <param name="path">The path.</param>
112 /// <param name="overwrite">if set to <c>true</c> [overwrite].</param>
113 /// <param name="ignoreMissingData">if set to <c>true</c> [ignore missing data].</param>
114 /// <param name="validateUrl">if set to <c>true</c> validate the url.</param>
115 public static void SetPicture(UserProfileManager profManager, string username, string path, bool overwrite, bool ignoreMissingData, bool validateUrl)
116 {
117 if (!string.IsNullOrEmpty(username))
118 {
119 if (!profManager.UserExists(username))
120 {
121 throw new SPException("The username specified cannot be found.");
122 }
123 UserProfile profile = profManager.GetUserProfile(username);
124 SetPicture(profile, path, overwrite, ignoreMissingData, validateUrl);
125 }
126 else
127 throw new ArgumentNullException("username", "The username parameter cannot be null or empty.");
128 }
129
130 /// <summary>
131 /// Sets the picture.
132 /// </summary>
133 /// <param name="up">Up.</param>
134 /// <param name="path">The path.</param>
135 /// <param name="overwrite">if set to <c>true</c> [overwrite].</param>
136 /// <param name="ignoreMissingData">if set to <c>true</c> [ignore missing data].</param>
137 /// <param name="validateUrl">if set to <c>true</c> validate the url.</param>
138 public static void SetPicture(UserProfile up, string path, bool overwrite, bool ignoreMissingData, bool validateUrl)
139 {
140 if (up["PictureURL"].Value != null && !string.IsNullOrEmpty(up["PictureURL"].Value.ToString()) && !overwrite)
141 {
142 Log("\"{0}\" already contains a picture URL. Specify -overwrite to replace existing settings.",
143 up["AccountName"].Value.ToString());
144 return;
145 }
146 if (string.IsNullOrEmpty(path))
147 {
148 path = string.Empty;
149 }
150 else
151 {
152 if (path.Contains("$(username)"))
153 {
154 if (up["UserName"] != null && up["UserName"].Value != null)
155 path = path.Replace("$(username)", up["UserName"].Value.ToString());
156 else
157 {
158 if (up["AccountName"] != null && up["AccountName"].Value != null)
159 path = path.Replace("$(username)", up["AccountName"].Value.ToString().Split('\\')[1]);
160 else
161 {
162 if (!ignoreMissingData)
163 throw new ArgumentException(string.Format("Unable to determine username from existing profile data ({0}).", up.ID));
164 return;
165 }
166 }
167 }
168
169 if (path.Contains("$(domain)"))
170 {
171 if (up["AccountName"] != null && up["AccountName"].Value != null)
172 path = path.Replace("$(domain)", up["AccountName"].Value.ToString().Split('\\')[0]);
173 else
174 {
175 if (!ignoreMissingData)
176 throw new ArgumentException(string.Format("Unable to determine domain from existing profile data ({0}).", up.ID));
177 return;
178 }
179 }
180
181 if (path.Contains("$(email)"))
182 {
183 if (up["WorkEmail"] != null && up["WorkEmail"].Value != null)
184 path = path.Replace("$(email)", up["WorkEmail"].Value.ToString());
185 else
186 {
187 if (!ignoreMissingData)
188 throw new ArgumentException(string.Format("Unable to determine email from existing profile data ({0}).", up.ID));
189 return;
190 }
191 }
192
193 if (path.Contains("$(firstname)"))
194 {
195 if (up["FirstName"] != null && up["FirstName"].Value != null)
196 path = path.Replace("$(firstname)", up["FirstName"].Value.ToString());
197 else
198 {
199 if (!ignoreMissingData)
200 throw new ArgumentException(string.Format("Unable to determine first name from existing profile data ({0}).", up.ID));
201 return;
202 }
203 }
204
205 if (path.Contains("$(lastname)"))
206 {
207 if (up["LastName"] != null && up["LastName"].Value != null)
208 path = path.Replace("$(lastname)", up["LastName"].Value.ToString());
209 else
210 {
211 if (!ignoreMissingData)
212 throw new ArgumentException(string.Format("Unable to determine lastname from existing profile data ({0}).", up.ID));
213 return;
214 }
215 }
216
217 if (path.Contains("$(employeeid)"))
218 {
219 if (up["EmployeeID"] != null && up["EmployeeID"].Value != null)
220 {
221 path = path.Replace("$(employeeid)", up["EmployeeID"].Value.ToString());
222 }
223 else
224 {
225 if (!ignoreMissingData)
226 throw new ArgumentException(string.Format("Unable to determine Employee ID from existing profile data ({0}).", up.ID));
227 return;
228 }
229 }
230 }
231
232 if (validateUrl)
233 {
234 Log("Validating URL \"{0}\" for \"{1}\".", path, up["AccountName"].Value.ToString());
235
236 //Create a request for the URL.
237 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(path);
238 request.AllowAutoRedirect = false;
239 request.Credentials = CredentialCache.DefaultCredentials;
240 HttpWebResponse serverResponse = (HttpWebResponse)request.GetResponse();
241 if (serverResponse.StatusCode != HttpStatusCode.OK)
242 {
243 Log("Unable to find picture. Setting PictureURL property to empty string.");
244 path = string.Empty;
245 }
246 serverResponse.Close();
247 }
248
249 Log("Setting picture for \"{0}\" to \"{1}\".", up["AccountName"].Value.ToString(), path);
250
251 up["PictureURL"].Value = path;
252 up.Commit();
253 }
254
255 }
256}
257#endif
The help for the command is shown below:
C:\>stsadm -help gl-setpictureurl
stsadm -o gl-setpictureurl
Sets the picture URL path for user profiles. The following variables may be used for dynamic replacement: "$(username)"
, "$(domain)", "$(email)", "$(firstname)", "$(lastname)", "$(employeeid)".
Parameters:
-path <path to new photo (i.e., "http://intranet/hr/EmployeePictures/$(username).jpg") - leave blank to clear>
[-sspname <name of the SSP>]
[-username <DOMAIN\name>]
[-overwrite]
[-ignoremissingdata]
[-validateurl]
The following table summarizes the command and its various parameters:
Command Name | Availability | Build Date |
---|---|---|
gl-setpictureurl | MOSS 2007 | Released: 9/18/2008 |
Parameter Name | Short Form | Required | Description | Example Usage |
---|---|---|---|---|
path | p | Yes | The path to the images. To substitute dynamic data use the following strings variables within the path: $(username), $(domain), $(email), $(firstname), $(lastname), $(employeeid). The variable names are case sensitive. | -path "http://intranet/hr/EmployeePictures/$(username).jpg" , -p "http://intranet/hr/EmployeePictures/$(username).jpg" |
sspname | ssp | No | The name of the SSP. If not specified then the default SSP will be used. | -sspname SSP1 , -ssp SSP1 |
username | u | No | The account name associated with the specific user profile to update. If omitted then all user profiles will be updated. | -username "domain\user" , -u "domain\user" |
overwrite | ow | No | If provided then existing data values will be overwritten. If omitted then any profile objects with existing data will be ignored. | -overwrite , -ow |
ignoremissingdata | ignore | No | If specified then do not error if a specified variable value cannot be found. Note that if the value is not found then the property value will not be set. | -ignoremissingdata , -ignore |
validateurl | validate | No | If specified then perform a web request to see if the resultant URL is valid. If the result is not valid then the property value will be set to an empty string. | -validaturl , -validate |
The following is an example of how to set the picture URL property of all user profiles:
stsadm -o gl-setpictureurl -path "http://intranet/hr/EmployeePictures/$(username).jpg" -overwrite
Updated 4/17/2009: The command has been updated to include the employeeid variable as well as the ignoremissingdata and the validateurl parameters. Thanks to Tim Griepp for providing some code that I used to motivate myself to look at this command again 🙂