CMS Made Simple & HostGator – Can’t upload files

I administer a CMS Made Simple site that runs on HostGator. I got a report from a user that they couldn’t upload any files. Strange! I checked it out, and neither could I (through the web interface). I could upload a file straight to the /uploads directory, but I couldn’t delete the file. It would complain about my actions being limited to the uploads folder… so it thought I wasn’t in it?

Logged into HostGator’s cPanel and found that my root path had changed from /home to /home4 … no notice from HostGator about this, it just changed.

Changed the config.php of the CMS Made Simple site to have /home4 wherever /home was before – all is working now.

CMS Made Simple – Post-Upgrade to v1.11.11

After finishing an upgrade of another site’s CMS Made Simple to version 1.11.11, I found that in certain areas I was seeing warning messages at the top of the screen after editing calendar events within CGCalendar. They looked like this:

Warning: Cannot modify header information - headers already sent by (output started at /home4/user/public_html/admin/moduleinterface.php:99) in /home4/user/public_html/include.php on line 96

Warning: Cannot modify header information - headers already sent by (output started at /home4/user/public_html/admin/moduleinterface.php:99) in /home4/user/public_html/include.php on line 99

Warning: Cannot modify header information - headers already sent by (output started at /home4/user/public_html/admin/moduleinterface.php:99) in /home4/user/public_html/include.php on line 102

Warning: Cannot modify header information - headers already sent by (output started at /home4/user/public_html/admin/moduleinterface.php:99) in /home4/user/public_html/include.php on line 103

Warning: Cannot modify header information - headers already sent by (output started at /home4/user/public_html/admin/moduleinterface.php:99) in /home4/user/public_html/include.php on line 106

Warning: Cannot modify header information - headers already sent by (output started at /home4/user/public_html/admin/moduleinterface.php:99) in /home4/user/public_html/include.php on line 109

The Solution
The solution I found was to change my Administration Theme preference from the older “NCleanGrey” to the newer “OneEleven”. This option is under My Preferences -> My Account -> User Preferences.

Tracing it down
I’m fairly new to PHP, having developed C# primarily the last few years. However, I believe what’s causing this is that within the moduleinterface.php file (line 99), it’s calling a “ShowMessage” function that’s supposed to exist within your preferred theme. The NCleanGrey theme has no such function, while the newer OneEleven theme does. Why this lack of a function causes it to yield these particular error messages, I have no idea. I’m trying to post a bug report on this, so perhaps it can be fixed in the next version of CMSMS. Until then, I’d suggest just using the new theme.

CMS Made Simple – Enable SSL for the Admin Directory

Recently updated a site I maintain that uses the great CMS Made Simple and had to reconfigure SSL (https) for the administrative areas of the site. I’ve done this previously, but had forgotten exactly what I did. Here’s all it takes:

  1. Get an SSL certificate configured on your domain. You can find instructions for that somewhere else.
  2. Modify the config.php file in the base directory. Find the line that’s setting up the “root_url” variable. Replace it with the following, replacing <hostname> with your site’s host name:
    $config['root_url'] = 'http://<hostname>';
    if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS']=='on') {
    $config['root_url'] = 'https://<hostname>';
    }
  3. Create an .htaccess file and place it in the admin directory (or whatever you’ve renamed it to). This file should contain the following:
    # force all access to /admin to SSL protected page
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

Done! Your admin directory should now require HTTPS. This works as of CMS Made Simple version 1.11.11.

Navigation DVD Replacement Tools – Lexus IS250/IS350

I decided to upgrade the navigation DVD in my car. Being who I am, this is a DIY project (once you get the DVD, of course). Followed the instructions from Sewell Parts, I hit a snag… what precision screwdrivers would fit?

I dug out my bag o’ tools and found the smallest screwdrivers. Tried them. No dice.

A friend of mine has a 2007 LS 460 and I noticed he had these tools in his trunk in a special bag. Searching my car, I could find no such tools. I couldn’t find much on the internet about this either. Where are the navigation DVD removal picks/screwdrivers in a Lexus IS 250/350?

They’re in the tool bag that has the tire iron. It’s somewhat L shaped, and mine was next to the spare tire. If you open the bag, the location of these tools is easy to overlook. Here’s a picture of where they’re at.

Lexus IS 250 350 tool bag navigation

Playing with Open Source Automation

We’re preparing to move into a new house and I’ve discovered that I’m interested in home automation. Well… not really home automation so much as the nerdy aspect of controlling physical things through code. This is a bit scary, as home automation can be quite expensive and if not done with an eye toward quality and usability can be very very frustrating.

Oh well. I was Googling the subject and found several open source home automation controllers. One of those is Open Source Automation. It’s .Net based and has a plugin system for extension. I’m a .Net developer by day (and some evenings and weekends…) so I found it pretty interesting. All kinds of what-if’s entered my brain:

  • Can I have it monitor my garage door to see if I left it up after I go to work?
  • Can I have it monitor the locks to the house to ensure that everything is locked up at night?
  • How about adjusting some blinds relative to the angle of the sun using some math and the sunrise/sunset times?

I talked a bit about it to my boss and employees and one of my employees said he had an older Z-Wave USB dongle and a Z-Wave module for plugging a lamp into. I borrowed these earlier today and am now working through setting up the Open Source Automation controller to see how far this will go. I suspect that the dongle is going to be too old for OSA to use, but we’ll just have to see…

Step 1 Install MySQL – Done!

Step 2 Install Open Source Automation…

Running the Installer, I got the following message: “There is a problem with this installer package…”:

Looking at the log, this is what’s occuring right when the error happens:

[0628:1D6C][2013-09-13T18:08:02]i323: Registering package dependency provider: {DA805477-316E-4344-96EF-180BD76854F0}, version: 0.4.3, package: ServerPackageIdx64
[0628:1D6C][2013-09-13T18:08:02]i301: Applying execute package: ServerPackageIdx64, action: Install, path: C:\ProgramData\Package Cache\{DA805477-316E-4344-96EF-180BD76854F0}v0.4.3\Server Installer x64.msi, arguments: ' ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="7" INSTALLFOLDER="C:\Program Files\OSA"'
[0628:1D6C][2013-09-13T18:10:48]e000: Error 0x80070643: Failed to install MSI package.
[0628:1D6C][2013-09-13T18:10:48]e000: Error 0x80070643: Failed to execute MSI package.

Perusing the Open Source Automation forums, I found this post talking about the same issue with the installer. It indicates that restarting the MySQL service may resolve the issue. So I restarted the service and…. same error.

The same post indicated that perhaps something else was running on port 8081 and to use tcpview to check it out. I used it – nothing’s running on port 8081.

I then found this post, which indicated that .Net 3.5 may be needed for the Web Server software to install. I’m running Windows 8, so this isn’t installed by default. Installed it. Ran the OSA installer… it worked! So yeah – .Net 3.5 is a pre-req that the installer doesn’t check for.

Step 3 – Get the Z-Wave USB dongle working.

Reading OSA’s wiki, I found that this particular (older) dongle, the Intermatic HA22,  isn’t support by the Open-ZWave library. So much for that.

Guess I’ll have to wait until I get some hardware that works with OSA… or find some other software that might work with the Intermatic HA22. Off to Google for that :)

SharePoint 2010 – MigrateUser Error “Value cannot be null. Parameter name: userProfileApplicationProxy”

When using the stsadm command:

stsadm.exe -o migrateuser oldlogin “domainusername” -newlogin “domainnewusername”

We received this error message:

Value cannot be null.
Parameter name: userProfileApplicationProxy

If you look in the ULS logs, you’ll find that there is an Access Denied event occuring. We were able to resolve this by going into Central Administration, selecting the User Service Application, and ensuring that the administrator account being used to run the above command has Full Control rights to the Service Application. You can find this by going to the following in Central Administration:

Application Management -> Manage Service Applications -> Select, but do not follow the link for your User Profile Sync service -> The “Permissions” button in the ribbon

IP30 Programming – Part 2

The batteries on the IP30 and CN3 are fully charged and ready for some tinkering.

Upgrading the Firmware from 3.01 to 3.16

I looked into upgrading the firmware on the IP30 and it looks to require a MiniSD card. MiniSD is the never-mentioned step brother of SD and MicroSD… meaning stores don’t carry it anymore. I’ve got a MiniSD card and reader on order from Amazon… so updating the IP30 will have to wait.

Available Commands

To receive the available commands on the IP30, the HELP command can be issued. Here’s the response for BRI 3.01 on the IP30:

Reading Tags

Issuing a READ command causes the IP30 to read all tags in the vicinity and report them back in one shot. Tested and this works. Turns out the 8 tags that I have for testing all have the same ID… not optimal but it will work for now.

Next

This is probably it for testing the IP30 with Windows and Tera Term. I’m going to activate my license to Xamarin (have to purchase just to deploy to the device…wish they had some better pricing for education) and get to programming.

Communicating with the Intermec IP30 RFID reader over bluetooth…hopefully with Android

I’m starting work on a project for my MBA program that involves using a mobile RFID reader with an Android device. I’ve purchased a Nexus 7 for the project, and the school has loaned me an Intermec IP30 RFID reader. I’m going to detail my steps in getting this going here.

10/5/2012

Acquired the IP30 from my university. This IP30 is attached to the Intermec CN3 handheld computer, which is running some old version of Windows Mobile. I’ve confirmed that the CN3 can actually communicate with the IP30 and read tags – yay! I don’t plan on using the CN3, but it’s a nice reference for how the communication is supposed to work.

The IP30 is communicated to from the CN3 by bluetooth. Intermec offers some libraries for C# development, but I won’t be using them as this will be an Android application. I’ll be using Xamarin’s Mono for Android (C#), but the Intermec assembly uses some Windows CE libraries so it’s no help. Luckily, it looks like the IP30 works with Intermec’s “Basic Reader Interface” or BRI. This is an ASCII-based protocol over serial/bluetooth. They even have a handy doc on all the relevant commands and how to structure your app if going straight against BRI.

At this point, my goal is to communicate with the IP30 using a hyperterminal on my Windows 7 box. I wore the battery down on the IP30 trying to use PUTTY to for communication and couldn’t manage to get it to respond to any command. I believe that I just wasn’t sending the necessary CRLF at the end of each command for the IP30 to respond, so I’ve downloaded a different hyperterminal – Bray++’s Terminal. Whenever the battery charges up for the IP30, I’ll start whittling at it again :)

Later…

Couldn’t get Bray’s Terminal to connect to the IP30. It would cause Windows to beep, then I’d not be able to connect to the IP30 with anything (including Putty) until I reset the connection by pulling the battery out of the IP30 and putting it back in.

I downloaded Tera Term and have success! It was indeed the newline setting for transmission. I had to change this setting in the Terminal setup and also enable local echo so I could see what I was typing…

This is what I’m seeing when issuing a command through Tera Term:

Luckily in my searching for IP30 related posts, I ran across a page on Intermec’s site where another developer was trying to do what I’m doing through HyperTerminal and had an issue. Issuing FACDFLT4 (which is issued in the BRI manual I referenced earlier) reset the device to factory settings – so I should be good to go!

To be continued…

SharePoint 2010: Observations and Revelations on the User Profile Sync Service and the Update-SPProfilePhotoStore cmdlet

These are my notes while trying to diagnose and better understnad some issues and oddities with the SharePoint 2010 User Profile Service Application.

If you’re wanting to populate pictures into people’s profiles, you’ll be using the Update-SPProfilePhotoStore powershell cmdlet after a normal sync (full or incremental – or your custom built one). This cmdlet is in the Microsoft.Office.Server.UserProfiles dll, specifically the Microsoft.Office.Server.UserProfiles.PowerShell.SPCmdletUserProfilePhotoStore class. Thanks to the goodness that is Redgate Reflector (a must have for any SP developer), we can get a more clear undertanding of what the cmdlet is doing. I’ve written some comments to help understand what’s going on, as well as renamed some variables for the section I was more interested in understanding. You’ll want to open the code in a new window (highlight on the top right of the code section), as some of the lines are quite long:

[Cmdlet("Update", "SPProfilePhotoStore")]
internal sealed class SPCmdletUserProfilePhotoStore : SPCmdlet
{
    // Fields
    private bool? m_createThumbnailsForImportedPhotos = null;
    private bool? m_noDelete = null;
    private SPFolder m_profilePicFolder;
    private SPSitePipeBind m_SiteMySiteHost;
    private UserProfileManager m_userProfileManager;

    // Constructor
    public SPCmdletUserProfilePhotoStore()
    {
        this.m_createThumbnailsForImportedPhotos = null;
        this.m_noDelete = null;
    }

    // Methods
    protected override void InternalProcessRecord()
    {
        // Run the below section if -CreateThumbnailsForImportedPhotos has NOT been specified.
        if (!this.m_createThumbnailsForImportedPhotos.HasValue)
        {
            // Enumerate through all UserProfiles
            foreach (UserProfile profile in this.m_userProfileManager)
            {
                try
                {
                    // Get the PictureURL property of the user profile
                    object obj2 = profile["PictureURL"].Value;
                    if ((obj2 != null) && !string.IsNullOrEmpty((string) obj2))
                    {
                        // This user has a PictureURL property. Get the path
                        string path = profile["PictureURL"].Value.ToString();
                        string format = StringResourceManager.GetString("Powershell_MovePictures_GenericError_Text");
                        format = string.Format(CultureInfo.InvariantCulture, format, new object[] { path, (string) profile["AccountName"].Value });

                        // If the PictureURL property has a link to the medium thumbnail, don't process further.
                        if (!Path.GetFileNameWithoutExtension(path).EndsWith("_MThumb", StringComparison.Ordinal))
                        {
                            bool flag = false;
                            byte[] buffer = null;
                            try
                            {
                                using (SPSite site = new SPSite(path))
                                {
                                    using (SPWeb web = site.RootWeb)
                                    {
                                        // Try and get a reference to the file specified. This can be in SharePoint somewhere on on another webserver.
                                        SPFile file = web.GetFile(path);
                                        if (file.Exists)
                                        {
                                            try
                                            {
                                                buffer = file.OpenBinary();
                                            }
                                            catch (Exception exception)
                                            {
                                                base.WriteError(new SPException(format + exception.ToString()), ErrorCategory.WriteError, null);
                                                buffer = null;
                                            }
                                        }
                                        else
                                        {
                                            // The file doesn't exist. Write an error.
                                            string str4 = StringResourceManager.GetString("Powershell_MovePictures_FileNotFound_Text");
                                            str4 = string.Format(CultureInfo.CurrentCulture, str4, new object[] { path });
                                            base.WriteError(new FileNotFoundException(format + str4), ErrorCategory.WriteError, null);
                                        }
                                    }
                                }
                            }
                            catch (FileNotFoundException)
                            {
                                // File wasn't found using Object Model. Maybe it's on another webserver. Try and open the file using a WebClient instead of the Object Model
                                try
                                {
                                    WebClient client = new WebClient();
                                    CredentialCache cache = new CredentialCache();
                                    cache.Add(new Uri(path), "Ntlm", CredentialCache.DefaultNetworkCredentials);
                                    client.Credentials = cache;
                                    buffer = client.DownloadData(new Uri(path));
                                }
                                catch (Exception exception2)
                                {
                                    base.WriteError(new SPException(format + exception2.ToString()), ErrorCategory.WriteError, null);
                                    buffer = null;
                                }
                            }
                            string str5 = null;
                            // Did we read the file into memory?
                            if (buffer != null)
                            {
                                string str7 = UrlUtility.ConvertToLegalFileName(profile["AccountName"].Value.ToString(), '_');
                                string str8 = ".jpg";
                                try
                                {
                                    using (MemoryStream stream = new MemoryStream(buffer))
                                    {
                                        using (Bitmap bitmap = new Bitmap(stream, true))
                                        {
                                            // Create a large thumbnail
                                            UserProfilePhotos.CreateThumbnail(bitmap, UserProfilePhotos.LargeThumbnailSize, UserProfilePhotos.LargeThumbnailSize, this.m_profilePicFolder, str7 + "_LThumb" + str8);
                                            // Create a medium thumbnail
                                            SPFile file2 = UserProfilePhotos.CreateThumbnail(bitmap, UserProfilePhotos.MediumThumbnailSize, UserProfilePhotos.MediumThumbnailSize, this.m_profilePicFolder, str7 + "_MThumb" + str8);
                                            // Create a small thumbnail
                                            UserProfilePhotos.CreateThumbnail(bitmap, UserProfilePhotos.SmallThumbnailSize, UserProfilePhotos.SmallThumbnailSize, this.m_profilePicFolder, str7 + "_SThumb" + str8);
                                            // Get a URL to the Medium Size Thumbnail
                                            str5 = UrlUtility.EnsureTrailingSlash(this.m_userProfileManager.MySiteHostUrl) + file2.Url;
                                        }
                                    }
                                }
                                catch (Exception exception3)
                                {
                                    base.WriteError(new SPException(format + exception3.ToString()), ErrorCategory.WriteError, null);
                                    flag = true;
                                }
                            }
                            // If the URL to the medium thumbnail isn't null and we successfully created the thumbnails...
                            if ((str5 != null) && !flag)
                            {
                                // Set the PictureURL value
                                profile["PictureURL"].Value = str5;
                                profile.Commit();
                                // Write to the log (verbose) that we set the Picture up.
                                string str9 = StringResourceManager.GetString("Powershell_MovePictures_PhotoMoved_Text");
                                str9 = string.Format(CultureInfo.InvariantCulture, str9, new object[] { profile["AccountName"].ToString(), DateTime.Now.ToLongTimeString() });
                                base.WriteVerbose(str9);
                            }
                        }
                    }
                }
                catch (Exception exception4)
                {
                    string str10 = StringResourceManager.GetString("Powershell_MovePictures_GenericError_Text");
                    str10 = string.Format(CultureInfo.InvariantCulture, str10, new object[] { string.Empty, (string) profile["AccountName"].Value });
                    base.WriteError(new SPException(str10 + exception4.ToString()), ErrorCategory.WriteError, null);
                }
            }
        }
        // Run the below section if -CreateThumbnailsForImported has been specified
        else
        {
            // Get the MySiteHost Site Collection
            using (SPSite site2 = new SPSite(this.m_userProfileManager.MySiteHostUrl))
            {
                // Access the MySiteHost RootWeb
                using (SPWeb web2 = site2.RootWeb)
                {
                    // Get the PhotoListURL
                    string importPhotoListUrl = UserProfileGlobal.GetImportPhotoListUrl(ProfileType.User) + "/" + UserProfileGlobal.GetImportPhotoFolderName(web2.Locale) + "/";
                    // Enumerate through all UserProfiles
                    foreach (UserProfile profile2 in this.m_userProfileManager)
                    {
                        // Get the filename of the photo, then the url to the photo, and finally the file itself
                        // This is a combination of the UserProfileManager PartitionID (internal property) and the RecordId of the profile. This is the temporary picture file.
                        string importPhotoFilename = UserProfileGlobal.GetImportPhotoFilename(this.m_userProfileManager, profile2.RecordId);
                        string importPhotoFilenameWithListUrl = importPhotoListUrl + importPhotoFilename;
                        SPFile file3 = web2.GetFile(importPhotoFilenameWithListUrl);

                        // If the file exists, run below.
                        if ((file3 != null) && file3.Exists)
                        {
                            // Format an error message in case we need it later.
                            string str15 = StringResourceManager.GetString("Powershell_MovePictures_GenericError_Text");
                            str15 = string.Format(CultureInfo.InvariantCulture, str15, new object[] { file3.ToString(), (string) profile2["AccountName"].Value });

                            // Try opening the file and reading it into memory
                            byte[] buffer2 = null;
                            try
                            {
                                buffer2 = file3.OpenBinary();
                            }
                            catch (Exception exception5)
                            {
                                // There was an exeption reading the picture file into memory. Write this error to a log, then set the buffer to null
                                base.WriteError(new SPException(str15 + exception5.ToString()), ErrorCategory.WriteError, null);
                                buffer2 = null;
                            }

                            // Check and see if we were able to read the file into memory successfully. Run below if we could.
                            if (buffer2 != null)
                            {
                                // We've got the temporary file in memory. Determine what we should rename it
                                string str17 = profile2["AccountName"].Value.ToString().Replace(@"\", "_");
                                string str18 = ".jpg";
                                string mediumThumbnailURL = null;
                                bool createThumbnailsSuccess = true;
                                try
                                {
                                    using (MemoryStream stream2 = new MemoryStream(buffer2))
                                    {
                                        using (Bitmap bitmap2 = new Bitmap(stream2, true))
                                        {
                                            // Create a Thumbnail - large size
                                            UserProfilePhotos.CreateThumbnail(bitmap2, UserProfilePhotos.LargeThumbnailSize, UserProfilePhotos.LargeThumbnailSize, this.m_profilePicFolder, str17 + "_LThumb" + str18);
                                            // Create a Thumbanil - medium size, and get a reference to the file it creates
                                            SPFile file4 = UserProfilePhotos.CreateThumbnail(bitmap2, UserProfilePhotos.MediumThumbnailSize, UserProfilePhotos.MediumThumbnailSize, this.m_profilePicFolder, str17 + "_MThumb" + str18);
                                            // Create a Thumbnail - small size
                                            UserProfilePhotos.CreateThumbnail(bitmap2, UserProfilePhotos.SmallThumbnailSize, UserProfilePhotos.SmallThumbnailSize, this.m_profilePicFolder, str17 + "_SThumb" + str18);
                                            // Build a URL that points to the medium size thumbnail
                                            mediumThumbnailURL = this.m_userProfileManager.MySiteHostUrl + file4.Url;
                                        }
                                    }
                                }
                                catch (Exception exception6)
                                {
                                    base.WriteError(new SPException(str15 + exception6.ToString()), ErrorCategory.WriteError, null);
                                    createThumbnailsSuccess = false;
                                }
                                // Have we successfully created the thumbnails and have a path to the medium thumbnail?
                                if (createThumbnailsSuccess && (mediumThumbnailURL != null))
                                {
                                    // Set the PictureURL property
                                    profile2["PictureURL"].Value = mediumThumbnailURL;
                                    profile2.Commit();
                                    // If -NoDelete wasn't specified, then delete the image with the Guid_ID pattern for this user profile.
                                    if (!this.m_noDelete.HasValue || (this.m_noDelete == false))
                                    {
                                        file3.Delete();
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    protected override void InternalValidate()
    {
        SPSite site = this.MySiteHostLocation.Read();
        if (site == null)
        {
            string message = StringResourceManager.GetString("Powershell_MovePictures_NullMySiteHost_Text");
            base.ThrowTerminatingError(new ArgumentException(message), ErrorCategory.InvalidArgument, null);
        }
        SPServiceContext serviceContext = SPServiceContext.GetContext(site);
        if (serviceContext == null)
        {
            string str2 = StringResourceManager.GetString("Powershell_MovePictures_ServerContextNotFound_Text");
            base.ThrowTerminatingError(new ArgumentException(str2), ErrorCategory.ObjectNotFound, null);
        }
        this.m_userProfileManager = new UserProfileManager(serviceContext);
        if (this.m_userProfileManager == null)
        {
            string str3 = StringResourceManager.GetString("Powershell_MovePictures_ProfManagerNotFound_Text");
            base.ThrowTerminatingError(new ArgumentException(str3), ErrorCategory.ObjectNotFound, null);
        }
        if (!this.m_userProfileManager.IsProfileAdmin)
        {
            string str4 = StringResourceManager.GetString("Powershell_MovePictures_NotProfileAdmin_Text");
            base.ThrowTerminatingError(new ArgumentException(str4), ErrorCategory.InvalidOperation, null);
        }
        try
        {
            this.m_profilePicFolder = UserProfileGlobal.GetOrCreatePictureFolder(this.m_userProfileManager);
        }
        catch (Exception exception)
        {
            base.ThrowTerminatingError(exception, ErrorCategory.ObjectNotFound, null);
        }
    }

    // Properties
    [Parameter(Mandatory=false)]
    public bool CreateThumbnailsForImportedPhotos
    {
        get
        {
            return this.m_createThumbnailsForImportedPhotos.Value;
        }
        set
        {
            this.m_createThumbnailsForImportedPhotos = new bool?(value);
        }
    }

    [ValidateNotNull, Parameter(Mandatory=true, ValueFromPipeline=true)]
    public SPSitePipeBind MySiteHostLocation
    {
        get
        {
            return this.m_SiteMySiteHost;
        }
        set
        {
            this.m_SiteMySiteHost = value;
        }
    }

    [Parameter(Mandatory=false)]
    public bool NoDelete
    {
        get
        {
            return this.m_noDelete.Value;
        }
        set
        {
            this.m_noDelete = new bool?(value);
        }
    }
}

From this we gather that the command has two modes depending on whether the -CreateThumbnailsForImportedPhotos flag is specified.

CreateThumbnailsForImportedPhotos specified

This mode appears intended for those who are importing their pictures from Active Directory (or other source) as a raw picture (Octet String for AD) in bytes.

CreateThumbnailsForImportedPhotos not specified

This mode appears intended for the use cases where the PictureURL property has been prepopulated with a URL that either points to an image in SharePoint or an image available on another web server. This mode still will create thumbnails for you, but it doesn’t look for the temporary pictures in the form {GUID}_ID to make the thumbnails from – it will try and access the picture located at the URL specified in the PictureURL property.

So – if you’re importing your pictures from Active Directory and a user removes their picture from the directory, there is no means in the powershell (or observed from the import process) to take care of removing the picture from SharePoint.

I’ll post more as more is learned. There doesn’t seem to be much information on some of these things.