MOSS MVP

I've moved my blog to http://blog.falchionconsulting.com!. Please update your links. This blog is no longer in use--you can find all posts and comments at my new blog; I will no longer be posting to this site and comments have been disabled.

Thursday, September 18, 2008

Set User Profile Picture URL Property using STSADM (revisited)

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
   2: using System;
   3: using System.Collections.Specialized;
   4: using System.Text;
   5: using Lapointe.SharePoint.STSADM.Commands.SPValidators;
   6: using Microsoft.Office.Server;
   7: using Microsoft.Office.Server.UserProfiles;
   8: using Lapointe.SharePoint.STSADM.Commands.OperationHelpers;
   9: using Microsoft.SharePoint;
  10: using System.Net;
  11:  
  12: namespace 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
Updated: 4/17/2009

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 :)

67 comments:

Mikey said...

Thanks very much! I needed this one, as our staff photos are located in an external application (phone system) but are saved as (username).jpg. You are my new Sharepoint hero! :D

Paisley said...

MINE TOO!

Paisley said...

Mine too

thanks for this - and the update urls in stps from other servers - you really are a hero!

Anonymous said...

I have pictures of employees that are in the format of (LastName, FirstName).jpg. I take it I have to rename all these to be the user Network ID, or is there something else I can do?

Steve said...

also can pictures be in folders to do this?

Gary Lapointe said...

You wouldn't have to rename - you could just do something like this:

stsadm -o gl-setpictureurl -path "http://intranet/hr/EmployeePictures/($(lastname), $(firstname)).jpg" -overwrite

Gary Lapointe said...

You can put the pictures anywhere you want - as long as they can be accessed via an http link and you can construct a repeatable URL to them given the variables available.

Anonymous said...

Very nice! This was almost exactly what I was looking for...

Would it be possible to change so the program checks if the picture exists in the share before updating the URL?

Only about 50% of our 5000 users have a photo at the moment...

Craig said...

I ran the installation commands and all reported "operation completed succesfully" - but I do not see the gl- commands when I run stsadm. I ran the install in my dev environment first, and everything worked with no issues. This is the first solution I have deployed. Suggestions on where I might start looking to resolve this. The commands work well in dev but I need them in Prod.

Gary Lapointe said...

Make sure you ran the addsolution and deploysolution commands. Check Central Admin (Solution Management) and verify that it deployed with no errors. Check your event log for errors. Check that the dll is in the GAC and the xml file is in the config folder (change the WSP file extension to CAB and open it up and you'll see the files I'm referring to). Try to deploy again using -force.

Craig said...

I did try to re-run the commands. i do see where it says to use the -force command. i'll check the items you listed and re-run with the -force. Thank you

C:...AdminTool>"C:\Program Files\..\12\BIN\stsadm.exe" -o addsolution -filename Lapointe.Share
Point.STSADM.Commands.wsp

A solution with the same name "lapointe.sharepoint.stsadm.commands.wsp" or id "
2625fbe6-4884-4666-a1ae-6b06f0db8a6f" already exists in the solution store.
Lapointe.SharePoint.STSADM.Commands.wsp: The Solution installation failed.


C:...AdminTool>"C:\Program Files\..\12\BIN\stsadm.exe" -o deploysolution -name Lapointe.ShareP
oint.STSADM.Commands.wsp -immediate -allowgacdeployment

The solution "lapointe.sharepoint.stsadm.commands.wsp" has already been deployed
. Use the force parameter to redeploy the solution.


C:...AdminTool>"C:\Program Files\..\12\BIN\stsadm.exe" -o execadmsvcjobs

Executing .
Operation completed successfully.

Craig said...

I ran the installation commands and all reported "operation completed succesfully" - but I do not see the gl- commands when I run stsadm. I ran the install in my dev environment first, and everything worked with no issues. This is the first solution I have deployed. Suggestions on where I might start looking to resolve this. The commands work well in dev but I need them in Prod.

Craig said...

success - I ran the install from the search server, not the main front end server. Everything was installed and working on the main front end server, just not on the server I ran the install from. i manually placed the files on the search server and now the commands appear when I run stsadm. Is this expected behavior?

Gary Lapointe said...

As long as you are not using the "-local" switch on the deploy (so use -immediate) then the commands should be available on all servers. If not then there's something going on with your timer service.

Anonymous said...

This is a great post. Just need to a way to set the picture URL back to the default SharePoint settings.

Jasper said...

I've used the set picture command with success, but for some reason a couple of users still have their old picture displayed. I think (but I'm not entirely sure) the users which have set / changed their own picture in the past didn't get updated with the new URL. I want to force the profile pictures and not allow the user to set any picture of him or herself. Any idea on why the update shouldn't succeed for some users? A sync / SharedServices issue?

Gary Lapointe said...

You can check if it got updated by checking the properties in the profile management pages. You can also prevent users from being able to update their pictures by editing the property settings. You might have to run "stsadm -o sync" to get the profile pictures to sync to all site collections.

Anonymous said...

Hello,

This tool is really helpfull. I'm trying to update all my profiles. When the picture exist I want it to update the profile and when there's no picture, I want it to continue down list of profiles without updating the url. I'm using the switch validateurl but when it reach a unreachable destination, the script stop there witout completing the remaining profiles. Am I doing something wrong or do I miss an argument?

Thanks

Denis Chicoine

Gary Lapointe said...

Denis - try again with the latest release. I've since added some error handling that will hopefully address the issue you are having.

Anonymous said...

Hi, thank you for your post and hard work. If I have users without a picture and they will upload via there mysite a picture, in which path the pictures will be uploaded? In the "new one (you command)" or in the standard-path (shared pictures..)? If "standard path" how can I change this?

Michael

Gary Lapointe said...

If users are uploading their own pictures they will go to their shared library on their mysite. My command is mostly just useful if you are not allowing your users to do this. If you want to allow this then you might want to add an event receiver to their site which can capture the image being saved and then rename it or move it to a central library and then update the profile with the new path.

Fowara said...

Thanks for this tool. I am currently getting this error can you tell me how to fix it.
Unable to determine Employee ID from existing profile data (00a6ac39-6618-4167-9
77b-c4cd21e642af)

Gary Lapointe said...

You need to have an EmployeeID property added to the profile - this property doesn't exist by default.

Fowara said...

Thank you for your quick response. I already have a employee ID filed setup that is mapped to AD.
Is this EmployeeID case sensitive?
Is there anything else that I may have done wrong?

Fowara said...

Ok I was able to run it I had some syntax issue. But now the image urls are like this :
http://intranet.mactec.com/Directory/EmployeePhotos/$(EmployeeID).jpg instead of EmployeeID being replaced.

Gary Lapointe said...

The variable name is case sensitive - you need to have it all lowercase.

Fowara said...

in sharepoint the name is EmployeeID and display name Employee ID. If I do not match the case I cannot run the command. I am not able to change the case for the property name.

Can it be a new property with a new name? Or is there any work around. Thanks so mcuh for your help.

Gary Lapointe said...

You misunderstand - the variable name is case sensitive - I'm doing a simple search and replace so what you pass in via the command line must be lowercase - the code uses EmployeeID to get the managed property.

Kyle said...

I only want to rename part of the url. We moved the mysites to a different web application. We need to rename the first part of the url.

From http:\\portalsite\username\image.jpg

to http:\\mysites\username\image.jpg


Can your tool accomplish this?

Gary Lapointe said...

This command won't do a straight up search and replace but you could easily tweak the code to do what you want.

Anonymous said...

We already have employeeID in the profile with uppercase "ID" that's mapped to AD. How would we work around this case sesitivity issue?

Gary Lapointe said...

There is a difference between a variable and a managed field - what you are passing in is a variable that is replaced with the value of the managed field. The variable must be lowercase, the managed field must be "EmployeeID".

Anonymous said...

So, with the static managed field of "EmployeeID", the only choice I have is to recompile your source code with case change, or to create a script that will enumerate all users with their respectable employeeID, and use your gl-setpictureurl to individually set their picture URL.

Ivan Angulo said...

Hi Gary,
This command is awesome!. Thanks for sharing your tools with the world. I am your newest fan!

Martin said...

Hi, I stored mit JPEG´s named like the Account ID Guid is. But $(ADGuid) (Display Name: Active Directory Id) doesn´t work...

Any idea to use the AD ID??

Thanks
Martin

Gary Lapointe said...

You'd need to pull the source down and add support for this property, recompile and deploy.

Nick said...

Hello,

these info is helpful. BUT, in my peoplesearch results page I still do not see the images that belong to the userprofile ? Once in the userprofile the image IS shown ?

Robban said...

Hi

Love this command but it has suddenly stopped working...

Now I keep getting an error:
Validating URL "http://intranet/Profile Pictures/magnus.andersson@emain.se.jpg" for "DOMAIN\magand".
Exception occured validating URL "http://intranet/Profile Pictures/magnus.andersson@email.se.jpg" (property not updated):
The remote server returned an error: (401) Unauthorized.

any ide anybody?

regars
Robban

Robert Eriksson said...

Hi

I have been running gl-setpictureurl for some time now and its been wonderful. However it just stoped working. The Command I use is:
stsadm -o gl-setpictureurl -path "http://intranet/Profile Pictures/$(email).jpg" -overwrite -ignore -validate

But now Im getting an 401 error, like this: Exception occured validating URL "http://intranet/Profile Pictures/test1@domain.com.jpg" (property not updated) - The remote server returned an error: (401) Unauthorized.

No configuration changes have been made exept updates from Microsoft.
Any idea why this is happening now?

best regards
Robert

Gary Lapointe said...

It's probably due to the loopback fix - see my post for the gl-setbackconnectionhostnames command.

Robert said...

Hi again...

I tried setting DisableLoopbackCheck to 1 and rebooted but it did not help... any more idea?

kind regards
Robert

Gary Lapointe said...

Not sure. Just omit the -validate parameter.

Robert said...

That worked, however that will sett all profiles to have a pic with its email addess. And the profiles that dont have a picture will then have a red X as its picture. Not the "anonymous" pic. So it helped but it also made a little mess.

br
Robert

Fowara said...

Hi,
The script works great. I have different issue hopefully someone here will be able to help.

The photo shows up fine on Profile and MySite but on team site some pictures show up on Contact Webpart and some does not. When I go the profile the photo is there but nevers shows up on team site. Again some photo does show and some does not. Any idea what could cause this and way to fix it?

Thanks

Gary Lapointe said...

Make sure the profile sync jobs are running. You can run "stsadm -o sync" to force it to run.

Gary Lapointe said...

Robert - Make sure that the user account you were running the command as has access to view the pictures from the server. If you get the same 401 error then troubleshoot from there.

Robert said...

Thanks Gary

If I go directly from a IE-browser to the picture it prompts for login. I then type the user that I am logged on as and it shows me the picture. Also the user that run the command. I tried open CMD with a specified user, the one I always used and with full MOSS and Windows rights. But 401 comes back. I am a little loss... but I can understand and see it's a permission problem some how...
I search on... :)

best regards
Robert

Robert said...

Hi again

Problem solved...
There was a stored password on the machine that was wrong. The command used that everytime, why I dont know. So I cleared the users in the Stored User Names and Passwords control panel applet, (Control keymgr.dll) and then it worked! Thanks again for you help and a great app!
BR
Robert

Naresh said...

Hi,
great tool,
some gotchas, if you want to clear the reference run
stsadm -o -gl-setpictureurl -path ""
if you want to keep the noimage if the image doesnot exist in the library run the above command to reset first and then run
stsadm -o gl-setpictureurl -path "path" -ignoremissingdata -overwrite

Thanks,
Naresh

Jose M. Tamez said...

Nick said...
Hello,

these info is helpful. BUT, in my peoplesearch results page I still do not see the images that belong to the userprofile ? Once in the userprofile the image IS shown ?

That's because you have to run an incremental or full crawl to get the changes in your indexes.

Anonymous said...

Hi Gary,

I really couldn't thank you enough for this immensely useful piece you've put together. It works like charm and also extends customization in Sharepoint to a whole new level!

Great work!!!

Larry XL-IT

Anonymous said...

Hi.. Can anybody tell me.. What is the method name which method, have been used in sharepoint 2010, while uploading the user profile photo to "User Photos" gallery..

I tried using .NET reflector tool, to see the method. But couldnt find the exact method. Please help me.

Anonymous said...

Hi - I've just started using sharepoint and I am currently working with Sharepoint Designer 2007. This may seem silly, but where do I add the command?
Basically, can you show me step by step where to add the command?
Thanks a lot,

Anonymous said...

Great utility. I think the exception that happens with the "validat" option is because the code needs to handle a System.Net.WebException, rather than check for a 404 return code. At least that would be the issue with the source as posted on today's date (which I borrowed, thanks).

Gary Lapointe said...

You can't do it through designer - you need to be a farm admin and install it on the server (the install instructions are on the downloads page).

James said...

Gary - First you SP Podcast interview was great 2 weeks back. Are you planning on updating the SetPictureURL command for SharePoint 2010?

Gary Lapointe said...

Thanks! I will eventually migrate this one - I honestly just haven't had the time (life keeps getting in the way :)). Hopefully I'll be able to get to it this summer.

Zdenka said...

Hi Mike
I like to use your great command extension. As I am updating 1500 user profiles, I need to know who were not updated or errors. Is there any possibility to save the command results to a log?
Thank you for your response.
Zdenka

Gary Lapointe said...

Zdenka - who's Mike? :)

You can dump the output of any command by simply piping it to a file:

stsadm -o ... > log.txt

Zdenka said...

Hi Gary,
oh, I'm terribly sorry to call you Mike. I had hard day...
It works!

Have a nice day.
Kind Regards
Zdenka

Gary Lapointe said...

No worries - just giving you a hard time :)

Aravindh said...

Sir,
I need a small help with Sharepoint. I am new user to sharepoint and I was to automate the upload of files into the Sharepoint from my computer. I can use Batch Files or VB Scripts. Please let me know whether it is possible to automate the uploading of files into the Sharepoint.

Gary Lapointe said...

I would recommend using powershell to upload files in bulk. There's several ways to do it - one easy way is to use webdav:

Copy-Item "c:\myfilestoupload\*.*" "\\mysites.hostheader.name\mylibrary\"

Fowara said...

Will these scripts work on Sharepoint 2010 as well or only on 2007?

Gary Lapointe said...

They will not work with 2010. I have plans to migrate to 2010 but just haven't had time.

Anonymous said...

I have downloaded the source code and cannot get it to compile. I have also downloaded the wsp template and added the 'gl-setpictureurl' code to the template. And I cannot get that to compile either. Can you help me by telling me what I am doing wrong? Thanks!

Gary Lapointe said...

Are you getting any errors when compiling? Do you have the correct version for your SharePoint environment (2007 or 2010)?