Group Policy Printers not installing after update KB3170455 – MS16-087

 

Microsoft changed the way printers are installed with update KB3170455 (MS16-087). Now, for printers to be installed using group policy, the print driver must be set as true under packaged in Print Management. Some vendors have not updated their drivers to make them packaged, but there is a way to force a package to be packaged.

 

Open regedit and go to HKLM\SYSTEM\CurrentControlSet\Control\Print\Environments\Windows *** (choose version)\Drivers\Version-3\**DriverName**

 

Set the attribute PrinterDriverAttributes to 1 and restart the print spooler on the server. The driver will now show true as packaged and will install using GPO.

Group Policy not applying to security filtered user or group

 

Came across an issue this week where a newly imaged computer would not apply group policies that were filtered to an Active Directory group. GPResult showed no reference of the group policy, but it did show that the user was in the correct AD group.

 

After much research, I found that Microsoft released a Security Update for Group Policy on June 14, 2016 (https://support.microsoft.com/en-us/kb/3163622). This security update changes the way a client workstation reads the group policy. Prior to this update being installed, if a GP was a user policy, the policy would have been read by the current user’s credentials. Once the security update is applied to the client’s workstation, all group policies are read by the computer account.

 

To fix the issue, go to the group policy in which has security filtering and click on the Delegation tab. Click Add and add Authenticated Users with Read permission. Or, you can add Domain Computers with Read permission. Adding the permission under the Delegation tab with either method, only allows the computer accounts to read the policy to apply it based on the security filter. It will not apply to all authenticated users or domain computers.

Sage 50–Automatic Backup – An unknown error occurred compressing the database files.

 

While setting up a new Sage 50 2015 server I kept getting an error message “An unknown error occurred compressing the database files.” After further troubleshooting with Microsoft Process Monitor (https://technet.microsoft.com/en-us/library/bb896645.aspx) I found that it was trying to put a temporary file in a folder called “Backup” inside the company folder. This is probably a rare condition and only seen if you try to select a backup folder other than the default.

Simply create a folder called “Backup” in the company folder and try it again.

Enterprise Google Chrome Extension Not Installing

 

Had a recent issue where a Google Chrome extension I built wasn’t installing via group policy. After a lot of troubleshooting I found an entry in HKLM\Software\Policies\Google\Chrome\ExtensionInstallSources. Once I deleted that entire registry key (not just the value), the and restarted Chrome, the extension installed using the pushed settings that is in HKLM\Software\Policies\Google\Chrome\ExtensionInstallSources.

SQL Select–Format for phone number

 

If you want to create a SQL query to format a phone number based on different formats that may be in a database you can use this. Modify to fit your needs.

### – Replace this with your 3 digit area code. This is used when only 7 digits are stored as the value.

Home/Cell – Replace this with your phone number column

 

   1: SELECT 

   2:       CASE

   3:           WHEN LEN(REPLACE(REPLACE(REPLACE(REPLACE(Home,')',''),'(',''),' ',''),'-','')) = '7'

   4:             THEN '###' + REPLACE(REPLACE(REPLACE(REPLACE(Home,')',''),'(',''),' ',''),'-','')

   5:           WHEN SUBSTRING (Home, 1, 1) = '1'

   6:             THEN SUBSTRING(REPLACE(REPLACE(REPLACE(REPLACE(Home,')',''),'(',''),' ',''),'-',''), 2, LEN(Home))

   7:             ELSE REPLACE(REPLACE(REPLACE(REPLACE(Home,')',''),'(',''),' ',''),'-','')

   8:       END As [Home Phone],

   9:       CASE

  10:           WHEN LEN(REPLACE(REPLACE(REPLACE(REPLACE(Cell,')',''),'(',''),' ',''),'-','')) = '7'

  11:             THEN '###' + REPLACE(REPLACE(REPLACE(REPLACE(Cell,')',''),'(',''),' ',''),'-','')

  12:           WHEN SUBSTRING (Cell, 1, 1) = '1'

  13:             THEN SUBSTRING(REPLACE(REPLACE(REPLACE(REPLACE(Cell,')',''),'(',''),' ',''),'-',''), 2, LEN(Cell))

  14:             ELSE REPLACE(REPLACE(REPLACE(REPLACE(Cell,')',''),'(',''),' ',''),'-','')

  15:       END As [Cell Phone]

  16:  

  17:   FROM DBNAME

Apple Account Auto Verify

 

A tool I wrote in C# that automatically verifies apple accounts. Below is a link to the source code (Visual Studio 2010), however if you meet the following criteria, you can use it without modifying the code.

  1. Windows computer running .Net 4.0
  2. Running Exchange 2010
  3. Know the username and password to the mailbox that the verification email from apple is in, or you know the username and password to an elevated account that has permission to view the mailbox that the verification email from apple is in.

http://www.brandonclaps.com/downloads/AppleAccountVerify.zip – Includes source code too

If you meet the above criteria, unzip and browse to AppleAccountVerify > bin > Release > and run AppleAccountVerify.exe

 

Code:

   1: private void button_Verify_Click(object sender, EventArgs e)

   2:        {

   3:            string Log = string.Empty;

   4:            using (StreamReader sr = new StreamReader(textBox_CSVFile.Text))

   5:            {

   6:                string line;

   7:                while ((line = sr.ReadLine()) != null)

   8:                {

   9:                    string[] data = line.Split(',');

  10:  

  11:                    string ExchAuthUsername = data[0];

  12:                    string ExchAuthPassword = data[1];

  13:                    string ExchAuthDomain = data[2];

  14:                    string Exch_User_Email = data[3];

  15:                    string AppleUsername = data[4];

  16:                    string ApplePassword = data[5];

  17:  

  18:                    string Verify = GetAppleVerifyURL(ExchAuthUsername, ExchAuthPassword, ExchAuthDomain, Exch_User_Email);

  19:  

  20:                    if (Verify != string.Empty)

  21:                    {

  22:                        WebBrowser web = new WebBrowser();

  23:                        web.ScriptErrorsSuppressed = true;

  24:                        web.Navigate(new Uri(Verify));

  25:  

  26:                        while (web.ReadyState != WebBrowserReadyState.Complete)

  27:                        {

  28:                            Application.DoEvents();

  29:                        }

  30:                        try

  31:                        {

  32:                            HtmlElement el = web.Document.All["appleID"];

  33:  

  34:                            el.SetAttribute("value", AppleUsername);

  35:                            el.SetAttribute("text", AppleUsername);

  36:  

  37:                            HtmlElement el2 = web.Document.All["accountpassword"];

  38:  

  39:                            el2.SetAttribute("value", ApplePassword);

  40:                            el2.SetAttribute("text", ApplePassword);

  41:  

  42:                            foreach (HtmlElement el3 in web.Document.All)

  43:                            {

  44:                                if (el3.GetAttribute("className") == "btn bigblue")

  45:                                {

  46:                                    if (el3.InnerText.ToLower() == "verify address")

  47:                                    {

  48:                                        el3.InvokeMember("click");

  49:                                    }

  50:                                }

  51:                            }

  52:                            Log = Log + Environment.NewLine + AppleUsername + " - Verified successfully.";

  53:                        }

  54:                        catch (Exception Ex)

  55:                        {

  56:                            Log = Log + Environment.NewLine + AppleUsername + " - " + Ex.Message.ToString();

  57:                        }

  58:  

  59:                        Log = Log + Environment.NewLine + AppleUsername + " - Finished reading line";

  60:                    }

  61:                }

  62:            }

  63:            Log = Log + Environment.NewLine + " - Complete";

  64:            textBox_Log.Text = Log;

  65:        

  66:        }

Updated 12/29/14 – Updated code below (source code includes update)

   1: private static string GetAppleVerifyURL(string ExchangeAuthUsername, string ExchangeAuthPassword, string ExchangeAuthDomain, string EmailAddressToLookIn)

   2:        {

   3:            string URL = string.Empty;

   4:            try

   5:            {

   6:                ExchangeService ExchService = new ExchangeService(ExchangeVersion.Exchange2010_SP2);

   7:                ExchService.Credentials = new WebCredentials(ExchangeAuthUsername, ExchangeAuthPassword, ExchangeAuthDomain);

   8:                ExchService.AutodiscoverUrl(EmailAddressToLookIn);

   9:  

  10:                FolderId InboxID = new FolderId(WellKnownFolderName.Inbox, EmailAddressToLookIn);

  11:                ItemView view = new ItemView(50, 0, OffsetBasePoint.Beginning);

  12:                view.OrderBy.Add(ItemSchema.DateTimeReceived, SortDirection.Descending);

  13:                view.PropertySet = new PropertySet(BasePropertySet.IdOnly, ItemSchema.DateTimeReceived, ItemSchema.Subject);

  14:                FindItemsResults<Item> findResults = ExchService.FindItems(InboxID, view);

  15:  

  16:                if (findResults != null && findResults.Items != null && findResults.Items.Count > 0)

  17:                    foreach (Item item in findResults.Items)

  18:                    {

  19:                        EmailMessage message = EmailMessage.Bind(ExchService, item.Id, new PropertySet(BasePropertySet.IdOnly, EmailMessageSchema.IsRead, ItemSchema.Body, ItemSchema.Subject, ItemSchema.Categories));

  20:  

  21:                        if (message.Subject.ToLower().Contains("verify your apple"))

  22:                        {

  23:                            string body = message.Body.Text;

  24:                            string[] AfterVerifyText = Regex.Split(body, "To verify this email address belongs to you");

  25:                            string[] BeginningOfURL = Regex.Split(AfterVerifyText[1], "<a href=\"");

  26:                            int Location_EndOfUrl = BeginningOfURL[1].IndexOf('"');

  27:                            URL = BeginningOfURL[1].Substring(0, Location_EndOfUrl);

  28:                            message.IsRead = true;

  29:                            message.Update(ConflictResolutionMode.AutoResolve);

  30:                        }

  31:                    }

  32:            }

  33:            catch (Exception)

  34:            {

  35:                return URL;

  36:            }

  37:  

  38:            return URL; 

  39:        }

SharePoint–Profile Pictures no longer show after MySite URL change

I was recently installed SharePoint 2013 and had it staged under a different hostname so that I could just migrate IP’s and create CNAME DNS records for minimal downtime. However I found that once I had everything swapped to the new server the profile photos wouldn’t work anymore and I kept getting error messages when running the User Profile Sync. The errors that showed up in the event log were from SharePoint Foundation and FIMSynchonizationService

Error: 8311 “An operating failed because the following certificate has validation errors. SSL policy error have been encountered. Error code ‘0x2’ ” – I found this issue to be related to the sync using the old URL but the web site in IIS had a different (correct) SSL certificate. Once I realized what was happening I deleted a CNAME DNS record I had “mysite2” and started getting the next error”

Error 6801: “The remote name could not be resolved: ‘mysite2.xxxxx.com’ – This is because I removed the CNAME DNS record.

 

To Fix

You need to use the trust tool Update-SPProfilePhotoStore and tell it of the change in Uri’s.

Update-SPProfilePhotoStore –MySiteHostLocation “https://mysite.xxxx.com/mysite/” -OldBaseUri "https://mysite2.xxxx.com/mysite/User Photos/Profile Pictures/" -NewBaseUri "https://mysite.xxxx.com/mysite/MySite/User Photos/Profile Pictures/"

SharePoint – Export All Documents on Site and Sub-Sites

 

I was eliminating a site on SharePoint that had over 50 sub-sites. I wanted an easy way to get all the documents in each site without having to manually visit each one. Here is an easy PowerShell script I came up with.

   1: #Created by Brandon Claps

   2: #9/25/14

   3: #Exports all documents under a specific site and sub-sites to a local directory

   4:  

   5: #Address of your SharePoint root site

   6: $MainSiteAddress = "https://sharepointsite.contoso.com"

   7:  

   8: #URL of what you you would like to gather. Type a single asterisk if you want everything

   9: $MatchURL = "*URLAddress*"

  10:  

  11: #Destination where you want to download the documents to

  12: $destination = "D:\Exported Documents"

  13:  

  14:  

  15: $Site = Get-SPSite $MainSiteAddress

  16: $WebCollection = $Site.AllWebs

  17:  

  18: foreach($Web in $WebCollection)

  19: {

  20:     foreach($List in $Web.Lists)

  21:     {

  22:         if($List.ParentWebUrl -like $MatchURL)

  23:         {

  24:             if($List.BaseTemplate -eq "DocumentLibrary")

  25:             {                                

  26:                 $webUrl = $MainSiteAddress + $List.ParentWebUrl

  27:                 $listUrl = $webUrl + "/" + $List.RootFolder.Url

  28:                 

  29:                 $web2 = Get-SPWeb -Identity $webUrl

  30:                 $list2 = $web2.GetList($listUrl)

  31:                 

  32:                 function ProcessFolder 

  33:                 {

  34:                     param($folderUrl)

  35:                     $folder = $web2.GetFolder($folderUrl)

  36:                     

  37:                     foreach ($file in $folder.Files) 

  38:                     {

  39:                         $destinationfolder = $destination + "/" + $List.ParentWebUrl.TrimStart("/").Replace("/","-") + "---" + $folder.Url 

  40:                         if (!(Test-Path -path $destinationfolder))

  41:                         {

  42:                             $dest = New-Item $destinationfolder -type directory 

  43:                         }

  44:                         

  45:                         $binary = $file.OpenBinary()

  46:                         $stream = New-Object System.IO.FileStream($destinationfolder + "/" + $file.Name), Create

  47:                         $writer = New-Object System.IO.BinaryWriter($stream)

  48:                         $writer.write($binary)

  49:                         $writer.Close()

  50:                     }

  51:                 }

  52:                 Write-Host "Downloading: " $listUrl 

  53:                 ProcessFolder($list2.RootFolder.Url)

  54:             

  55:                 foreach ($folder in $list2.Folders) {

  56:                     ProcessFolder($folder.Url)

  57:                 }                                

  58:             }        

  59:         }        

  60:     }

  61:  }

Check group membership from AD with Foreign Security Principals

The following code will check if a user is a member of a specific group. This will work with a domain trust and Foreign Security Principals.

See the update below!

groupName = The sAMAccountName of the group you want to check the members of.
SearchDomain = This is the FQDN that you will be searching for the group. Ex: contoso.com
userName = This is the sAMAccountName of the user that you are checking if they are part of the group.
userDomain = This is the NetBIOS name of the domain of the user that you are checking. This really only comes into play when you are checking a user from a domain trust. Ex. CONTOSO
UserIsNativeDomain = This is true if the user you are checking is in the SearchDomain. If this is false, the user is in a domain trust and the code should be looking for the Foreign Security Principal and matching it to the userDomain and userName.

static bool CheckIfGroupMember(string groupName, string SearchDomain, string userName, string userDomain, bool UserIsNativeDomain)

        {

            bool GroupMember = false;                         

            string UserDN = string.Empty;           

            string FullLogonName = userDomain + "\\" + userName;

 

           if (UserIsNativeDomain == true)               

            {

                try //Get User's distinguishedName

                {                    

                    System.DirectoryServices.DirectoryEntry entry2 = new System.DirectoryServices.DirectoryEntry("LDAP://" + SearchDomain);

                    System.DirectoryServices.DirectorySearcher mySearcher2 = new System.DirectoryServices.DirectorySearcher(entry2);

                    mySearcher2.Filter = "(&(objectCategory=person)(ObjectClass=user)(sAMAccountName=" + userName + "))";

                    mySearcher2.PageSize = 1000;

                    System.DirectoryServices.SearchResult sr2 = mySearcher2.FindOne();

                    if (sr2 != null)

                    {

                        System.DirectoryServices.DirectoryEntry de2 = sr2.GetDirectoryEntry();

                        UserDN = de2.Properties["distinguishedName"].Value.ToString();

                        de2.Close();

                    }

                }

                catch (DirectoryServicesCOMException e2) { Console.Write(e2.Message); }

            }

 

            try //Check Group Membership

            {

                System.DirectoryServices.DirectoryEntry entry = new System.DirectoryServices.DirectoryEntry("LDAP://" + SearchDomain);

                System.DirectoryServices.DirectorySearcher mySearcher = new System.DirectoryServices.DirectorySearcher(entry);

                mySearcher.Filter = "(&(objectCategory=group)(sAMAccountName=" + groupName + "))";

                mySearcher.PageSize = 1000;

                System.DirectoryServices.SearchResult sr = mySearcher.FindOne();

                System.DirectoryServices.DirectoryEntry de = sr.GetDirectoryEntry();

 

                object[] members = (object[])de.Properties["member"].Value;

                foreach (object member in members)

                {

                    if (UserIsNativeDomain == false &&

                        member.ToString().Contains("CN=S-1-5"))   //If group member is a Foreign Security Principal

                    {

                        if (GetUserNameOfFSP(member.ToString()).ToLower() == FullLogonName.ToLower())

                        {

                            GroupMember = true;

                            break;

                        }

 

                    }

                    else

                    {

                        if (member.ToString().ToLower() == UserDN)

                        {

                            GroupMember = true;

                            break;

                        }

                    }

                }

                de.Close();

                return GroupMember;

            }

            catch (DirectoryServicesCOMException e) { Console.Write(e.Message); }

            return GroupMember;

        }

UPDATE 5/19/14: While working on an Active Directory Migration project using ADMT I found an issue with the code above. If you’re migrating a user from the source domain who is a member in a group in the target domain already it uses a Foreign Security Principal. Well after the ADMT migrates the user to the target domain, the user still shows as a Foreign Security Principal in the target domains group but with an updated domain name in the ForeignSecurityPrincipal OU. This new code will resolve that issue and handle it as necessary.

groupName = The sAMAccountName of the group you want to check the members of.

groupDomain = This is the FQDN that you will be searching for the group. Ex: contoso.com

userName = This is the sAMAccountName of the user that you are checking if they are part of the group.

userDomain = This is the NetBIOS name of the domain of the user that you are checking. Ex. CONTOSO

static bool CheckIfGroupMember(string groupName, string groupDomain, string userName, string userDomain)

{          

    bool GroupMember = false;

    string UserDN = string.Empty;

    string FullLogonName = userDomain + "\\" + userName;

 

    try //Get User's distinguishedName

    {

        DirectoryEntry entry2 = new DirectoryEntry("LDAP://" + userDomain);

        DirectorySearcher mySearcher2 = new DirectorySearcher(entry2);

        mySearcher2.Filter = "(&(objectCategory=person)(ObjectClass=user)(sAMAccountName=" + userName + "))";

        mySearcher2.PageSize = 1000;

        SearchResult sr2 = mySearcher2.FindOne();

        if (sr2 != null)

        {

            DirectoryEntry de2 = sr2.GetDirectoryEntry();

            UserDN = de2.Properties["distinguishedName"].Value.ToString();

            de2.Close();

        }

        entry2.Close();

    }

    catch (DirectoryServicesCOMException e2) { Console.Write(e2.Message); }

  

 

    try //Check Group Membership

    {

        DirectoryEntry entry = new DirectoryEntry("LDAP://" + groupDomain);

        DirectorySearcher mySearcher = new DirectorySearcher(entry);

        mySearcher.Filter = "(&(objectCategory=group)(sAMAccountName=" + groupName + "))";

        mySearcher.PageSize = 1000;

        SearchResult sr = mySearcher.FindOne();

        DirectoryEntry de = sr.GetDirectoryEntry();

 

        object[] members = (object[])de.Properties["member"].Value;

        foreach (object member in members)

        {

            if (member.ToString().Contains("CN=S-1-5"))

            {

                string FSPName = GetUserNameOfFSP(member.ToString().ToLower());

                if (FSPName.ToLower() == FullLogonName.ToLower())

                {

                    GroupMember = true;

                    break;

                }

            }

            else

            {

                if (member.ToString().ToLower() == UserDN.ToLower())

                {

                    GroupMember = true;

                    break;

                }

            }                

        }             

    }

    catch (DirectoryServicesCOMException e) { Console.Write(e.Message); }

 

    return GroupMember;

}

Microsoft Word – Mail Merge Separate Documents and Save File Name as Mail Merge Variable

Setup your Microsoft Word mail merge by selecting your data source and the recipients. Don’t actually complete the mail merge.

Create two Macro’s, one called “StartMailMerge” and the other called “DoWork”.

 

StartMailMerge – Code

Sub Start()

For i = 1 To ActiveDocument.MailMerge.DataSource.RecordCount

    DoWork

Next i

End Sub

DoWork – Code

Sub DoWork()

    Dim DokName  As String

 

    With ActiveDocument.MailMerge

        .Destination = wdSendToNewDocument

        .SuppressBlankLines = True

        With .DataSource

            .FirstRecord = ActiveDocument.MailMerge.DataSource.ActiveRecord

            .LastRecord = ActiveDocument.MailMerge.DataSource.ActiveRecord

            DokName = .DataFields("FieldName").Value      'Change "FieldName" to your MailMerge field name

        End With

 

' Merge the active record

        .Execute Pause:=False

    End With

 

' Save the resulting document.

    ActiveDocument.SaveAs2 FileName:="C:\temp\"+ DokName + ".docx", FileFormat:= _

        wdFormatXMLDocument, LockComments:=False, Password:="", AddToRecentFiles _

        :=True, WritePassword:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts _

        :=False, SaveNativePictureFormat:=False, SaveFormsData:=False, _

        SaveAsAOCELetter:=False, CompatibilityMode:=14

 

' Close the resulting document

    ActiveWindow.Close

 

' Now, back in the template document, advance to next record

    ActiveDocument.MailMerge.DataSource.ActiveRecord = wdNextRecord

End Sub

When you’re finished, just run the StartMailMerge macro.