Joseph Michael Pesch
VP Programming

Powershell Script to set full access to folders in Windows

by 28. May 2022 18:30

Powershell Script to set full access to folders in Windows:


$AccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("user_name","FullControl","Allow")

function Get-Folders {


    $list = ''

    $comma = ""

    foreach ($folder in Get-ChildItem -Path $path -Recurse -Directory) {

        Write-Output $folder.FullName

        $ACL = Get-ACL -Path $folder.FullName


        $ACL | Set-Acl -Path $folder.FullName

        Get-Folders $folder.FullName



Get-Folders 'C:\ProgramData\Docker'



Sending Email Through SMTP Using TELNET

by 16. September 2015 05:17

1) Open a cmd prompt.

2) Enter telnet <the FQDN of your SMTP server> <the port number>


3) Enter EHLO <the DNS domain name where the SMTP server is at>


If you get a successful connection you will see this:


4) Enter MAIL FROM: <the email address of the Workflow Run As Account>


5) Enter RCPT TO: <some email address you want to send to>


6) Enter DATA


7) Enter SUBJECT: <some subject you want to have> and hit Enter TWO times:


8) Enter a message body followed by Enter, then a period, then Enter again.


9: Enter QUIT



Window Update Slow or Stuck Checking for Updates

by 25. November 2014 06:53

After a fresh install of Windows 7 my Windows Update would take a long time (and typically never finish) when Checking for Updates.  In order to fix this I followed the steps below:

  1. Open the Windows Update panel and set to “Never Check For Updates (Not Recommended)”
  2. Stop the Windows Update Service (cmd: net stop wuauserv)
  3. Delete the folder: "C:\Windows\SoftwareDistribution"
  4. Restart the Windows Update Service (cmd: net start wuauserv)
  5. Download and install the two KB updates listed below:




Sharepoint 2010 Development on Windows 7 Virtual Machine

by 22. July 2013 07:01

Sharepoint 2010 Registry Entries

I recently installed a development machine with the necessary tools to perform SharePoint development on a Windows 7 64bit virtual machine.  The machine was then used as a master for a set of 7 virtual desktop developer workstations.  The issue; however, was that the inital intallations created several registry entries that referenced the original machine name.  This rendered the Sharepoint environment broken on all the virtual desktops (as each one had a different unique machine name).  To resolve this, I went back through the registry on the master and change the original machine name to "LOCALHOST" virtual name on all the following registry entries.  NOTE: The initial symptom manifest itself initially when opening the browser and attempting to browse to the local sharepoint site (in this case htt://localhost).  The page threw the follwing error: "Cannot connect to the configuration database."  Upon reviewing the log Sharepoint files (C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\LOGS\...) I noticed the original machine name in the failed connection attempt log entry.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\14.0\LauncherSettings\LoadBalancerUrl
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\14.0\Search\Applications\c0e071e1-533e-457a-8a61-8a86a6b78dcd\Gather\Portal_Content\ContentSources\0\StartPages\0\URL
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\14.0\Search\Applications\c0e071e1-533e-457a-8a61-8a86a6b78dcd\Gather\Portal_Content\ContentSources\0\StartPages\1\URL
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\14.0\Search\Applications\c0e071e1-533e-457a-8a61-8a86a6b78dcd\ResourceManager\ (several entries)
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0\Search\Applications\fd2e5092-25e3-46cf-8fc6-d62c85334b3d\Gather\Search\ContentSources\0\StartPages\0\URL
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0\Search\Applications\fd2e5092-25e3-46cf-8fc6-d62c85334b3d\ResourceManager\ (several entries)

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0\Secure\ConfigDB\dsn
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\Web Server Extensions\14.0\WSS\CentralAdministrationURL


Sharepoint | Virtual PC | Windows

Microsoft Fix It - Clean Removal Tool Replacement for MSICUU2.exe

by 24. February 2013 09:13

Some times when a software becomes corrupted and you attempt to uninstall/reinstall the software it may be in left in a bad state where it is unusable, leaving you with the only option to reformat your hard drive to reinstall your operating system or attempt to manually fix/unistall which can be very tedious and potentially error prone leaving your system in even a worse state.  The Windows Installer Clean Up tool developed by Microsoft "MSICUU2.exe" was a free and very useful tool to help fix these type of program removal/reinstallation issues.  However, Microsoft decided to retire this tool in 2010 and they have replaced it with another tool called “Microsoft Fix It” which is a progam install and uninstall utility that supports both 32-bit and 64-bit of Windows including Windows 7.  The tool can be run directly from the Microsoft web site; or, it can be downloaded and loaded onto a flash drive, CD, etc. to run locally on an affected machine.

In my case I had Symantec anti-virus software installed and attempted to remove it using the standard Windows Add/Remove Programs from the Control Panel.  However, my uninstall froze in the middle and left my PC in a state where it was gone from the Add/Remove Programs list but not fully removed from my PC.  Worse yet whenever I right-clicked on folders it would prompt me with a series of dialog boxes about trying to install Symantec and can't install.  I was able to successfully remove it using the Microsoft Fix It tool.

Download the tool directly from the Microsoft site:



Windows Command ForFiles to Search Folders/Sub-Folders and Output File Details

by 22. October 2012 12:23

Below is a sample command to search a folder (/p) and all subfolders (/s) for files mathing *.zip (/m)
and run echo command (/c) to print the filename, size, date and time to a text file

forfiles /p c:\foldertosearch /s /m *.zip /c "cmd /c echo @file;@fsize;@fdate @ftime" > output.txt

See Microsoft site for full usage of forfiles:



C# Application to Toggle Between Multiple Windows for Specified Time Interval

by 19. May 2011 08:12

This application allows you to define windows with intervals and then when started it will toggle between those windows at the specified interval.


ToggleWindows.zipx (70.15 kb)


C# | Windows

Get System Font List in C# Using Shell32.dll

by 31. December 2008 16:06

Creates a key/value dictionary of FontName/FontFile from the system fonts.  Also, contains a method to that accepts an output path which will be filled with image files (.png format) of sample text of each of the fonts. 

Original source of API code:

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
// Call the FontUtil.FontTool.BuildSampleFontImages() to generate sample image files of the fonts.
 // Sample usage:
   FontUtil.FontList fnt = FontUtil.FontList.GetInstance();
   IEnumerator en = fnt.FontMap.GetEnumerator();
   while (en.MoveNext())
     string FontName = ((System.Collections.Generic.KeyValuePair<string, string>)en.Current).Key;
     string FontFile = ((System.Collections.Generic.KeyValuePair<string, string>)en.Current).Value;
namespace FontUtil
   public static class FontTool
     public static void BuildSampleFontImages(string OutputPath)
       // The output path will be filled with image files (.png format) of sample text
       // of each of the fonts in the system that don't contain the words " bold" or " italic"
       // Also, checks after setting the since some of the fonts don't seem to register (see "Font Error" section).
       // NOTE: It will delete any existing image file with the same name before creating the new image.
       Font font = new Font("Times", 20);
       string FilePath = OutputPath;
       FontUtil.FontList fnt = FontUtil.FontList.GetInstance();
       IEnumerator en = fnt.FontMap.GetEnumerator();
       while (en.MoveNext())
         string text = ((System.Collections.Generic.KeyValuePair<string, string>)en.Current).Key;
           // Skip bold and/or italic versions of the fonts.
           if (text.ToLower().Contains(" bold") || text.ToLower().Contains(" italic"))
           font = new Font(text, 12);
           if (font.FontFamily.Name.ToLower() != text.ToLower())
             System.Diagnostics.Debug.WriteLine("Font Error: " + text);
           FilePath = System.Web.HttpContext.Current.Server.MapPath("") + @"\images\fonts\" + text.Replace(" ", "_") + ".png";
           text += (char)10 + "1234567890";
           text += (char)10 + "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.";
           text += (char)10 + "The quick brown fox jumps over the lazy dog.";
           CreateTextImage(text, font, FilePath);
         catch (Exception ex)
     private static void CreateTextImage(string text, Font font, string FilePath)
       Graphics g = Graphics.FromImage(new Bitmap(10, 10));
       SizeF sf = g.MeasureString(text, font);
       Bitmap bmp = new Bitmap(Convert.ToInt16(sf.Width), Convert.ToInt16(sf.Height));
       g = Graphics.FromImage(bmp);
       StringFormat strFormat = new StringFormat();
       strFormat.Alignment = StringAlignment.Center;
       strFormat.LineAlignment = StringAlignment.Center;
       // Color bgColor = Color.FromArgb(50, Color.Black); // 50% transparent black
       Color bgColor = Color.Transparent;
       g.FillRectangle(new SolidBrush(bgColor), 0, 0, Convert.ToInt16(sf.Width), Convert.ToInt16(sf.Height));
       g.DrawString(text, font, Brushes.Black,
        new RectangleF(0, 0, sf.Width, sf.Height), strFormat);
       bmp.Save(FilePath, ImageFormat.Png);
   public class FontList
     public Dictionary<string, string> FontMap = new Dictionary<string, string>();
     private static FontList inst;
     private FontList()
     public static FontList GetInstance()
       if (inst == null)
         inst = new FontList();
       return inst;
     private void GetAllFonts()
       //string fp = Environment.GetFolderPath((Environment.SpecialFolder) 0x14);//CSIDL_FONTS = 0x0014
       StringBuilder sb = new StringBuilder();
       SHGetFolderPath(IntPtr.Zero, 0x0014, IntPtr.Zero, 0x0000, sb);//CSIDL_FONTS = 0x0014
       string fontDir = sb.ToString();
       if (!Directory.Exists(fontDir))
       string[] fonts = Directory.GetFiles(fontDir);
       for (int i = 0; i < fonts.Length; i++)
         string name = GetFontName(fonts[i]);
         if (name != "")
           FontMap.Add(name, fonts[i]);
     private TT_OFFSET_TABLE ttResult;
     private TT_TABLE_DIRECTORY tbName;
     private TT_NAME_TABLE_HEADER ttNTResult;
     private TT_NAME_RECORD ttNMResult;
     private string GetFontName(string fontPath)
       string result = "";
       FileStream fs = new FileStream(fontPath, FileMode.Open, FileAccess.Read);
       BinaryReader r = new BinaryReader(fs, Encoding.UTF8);
       byte[] buff = r.ReadBytes(Marshal.SizeOf(ttResult));
       buff = BigEndian(buff);
       IntPtr ptr = Marshal.AllocHGlobal(buff.Length);
       Marshal.Copy(buff, 0x0, ptr, buff.Length);
       ttResult = (TT_OFFSET_TABLE)Marshal.PtrToStructure(ptr, typeof(TT_OFFSET_TABLE));
       //Must be maj =1 minor = 0
       if (ttResult.uMajorVersion != 1 || ttResult.uMinorVersion != 0)
         return "";
       bool bFound = false;
       tbName = new TT_TABLE_DIRECTORY();
       for (int i = 0; i < ttResult.uNumOfTables; i++)
         byte[] bNameTable = r.ReadBytes(Marshal.SizeOf(tbName));
         IntPtr ptrName = Marshal.AllocHGlobal(bNameTable.Length);
         Marshal.Copy(bNameTable, 0x0, ptrName, bNameTable.Length);
         tbName = (TT_TABLE_DIRECTORY)Marshal.PtrToStructure(ptrName, typeof(TT_TABLE_DIRECTORY));
         string szName =
           tbName.szTag1.ToString() +
           tbName.szTag2.ToString() +
           tbName.szTag3.ToString() +
         if (szName != null)
           if (szName.ToString() == "name")
             bFound = true;
             byte[] btLength = BitConverter.GetBytes(tbName.uLength);
             byte[] btOffset = BitConverter.GetBytes(tbName.uOffset);
             tbName.uLength = BitConverter.ToUInt32(btLength, 0);
             tbName.uOffset = BitConverter.ToUInt32(btOffset, 0);
       if (bFound)
         fs.Position = tbName.uOffset;
         byte[] btNTHeader = r.ReadBytes(Marshal.SizeOf(ttNTResult));
         btNTHeader = BigEndian(btNTHeader);
         IntPtr ptrNTHeader = Marshal.AllocHGlobal(btNTHeader.Length);
         Marshal.Copy(btNTHeader, 0x0, ptrNTHeader, btNTHeader.Length);
         ttNTResult = (TT_NAME_TABLE_HEADER)Marshal.PtrToStructure(ptrNTHeader, typeof(TT_NAME_TABLE_HEADER));
         bFound = false;
         for (int i = 0; i < ttNTResult.uNRCount; i++)
           byte[] btNMRecord = r.ReadBytes(Marshal.SizeOf(ttNMResult));
           btNMRecord = BigEndian(btNMRecord);
           IntPtr ptrNMRecord = Marshal.AllocHGlobal(btNMRecord.Length);
           Marshal.Copy(btNMRecord, 0x0, ptrNMRecord, btNMRecord.Length);
           ttNMResult = (TT_NAME_RECORD)Marshal.PtrToStructure(ptrNMRecord, typeof(TT_NAME_RECORD));
           // this is where the font name is recovered
           // to get the font family name (not incl 'bold' etc) use ttNMResult.uNameID == 1
           // see
           if (ttNMResult.uNameID == 4)
             long fPos = fs.Position;
             fs.Position = tbName.uOffset + ttNMResult.uStringOffset + ttNTResult.uStorageOffset;
             char[] szResult = r.ReadChars(ttNMResult.uStringLength);
             if (szResult.Length != 0)
               // some fonts are \0 A \0 r \0 i \0 a \0 l.... UTf8 encoding doesn't help
               if (szResult[0] == '\0')
                 int count = 0;
                 char[] temp = new char[szResult.Length / 2];
                 for (int j = 1; j < szResult.Length; j += 2)
                   temp[count++] = szResult[j];
                 szResult = temp;
               result = new String(szResult);
       return result;
     private byte[] BigEndian(byte[] bLittle)
       byte[] bBig = new byte[bLittle.Length];
       for (int y = 0; y < (bLittle.Length - 1); y += 2)
         byte b1, b2;
         b1 = bLittle[y];
         b2 = bLittle[y + 1];
         bBig[y] = b2;
         bBig[y + 1] = b1;
       return bBig;
     static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, IntPtr hToken,
      uint dwFlags, [Out] StringBuilder pszPath);
     [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
     struct TT_OFFSET_TABLE
       public ushort uMajorVersion;
       public ushort uMinorVersion;
       public ushort uNumOfTables;
       public ushort uSearchRange;
       public ushort uEntrySelector;
       public ushort uRangeShift;
     [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
       public char szTag1;
       public char szTag2;
       public char szTag3;
       public char szTag4;
       public uint uCheckSum; //Check sum
       public uint uOffset; //Offset from beginning of file
       public uint uLength; //length of the table in bytes
     [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
       public ushort uFSelector;
       public ushort uNRCount;
       public ushort uStorageOffset;
     [StructLayout(LayoutKind.Sequential, Pack = 0x1)]
     struct TT_NAME_RECORD
       public ushort uPlatformID;
       public ushort uEncodingID;
       public ushort uLanguageID;
       public ushort uNameID;
       public ushort uStringLength;
       public ushort uStringOffset;


Tags: ,

C# | Windows

Windows File Copy/Move Permissions Rules

by 18. November 2008 14:28

When copying or moving files in windows, the following matrix of rules applies to how permissions are either retained from the source or inherited from the target.

Permission Matrix











Target Location 




RoboCopy Usage Info

by 18. November 2008 14:25

   ROBOCOPY     ::     Robust File Copy for Windows                             

  Started : Mon Aug 25 09:31:13 2008

              Usage :: ROBOCOPY source destination [file [file]...] [options]

             source :: Source Directory (drive:\path or \\server\share\path).
        destination :: Destination Dir  (drive:\path or
               file :: File(s) to copy  (names/wildcards: default is "*.*").

:: Copy options :
                 /S :: copy Subdirectories, but not empty ones.
                 /E :: copy subdirectories, including Empty ones.
             /LEV:n :: only copy the top n LEVels of the source directory tree.

                 /Z :: copy files in restartable mode.
                 /B :: copy files in Backup mode.
                /ZB :: use restartable mode; if access denied use Backup mode.
            /EFSRAW :: copy all encrypted files in EFS RAW mode.

  /COPY:copyflag[s] :: what to COPY for files (default is /COPY:DAT).
                       (copyflags : D=Data, A=Attributes, T=Timestamps).
                       (S=Security=NTFS ACLs, O=Owner info, U=aUditing info).

           /DCOPY:T :: COPY Directory Timestamps.

               /SEC :: copy files with SECurity (equivalent to /COPY:DATS).
           /COPYALL :: COPY ALL file info (equivalent to /COPY:DATSOU).
            /NOCOPY :: COPY NO file info (useful with /PURGE).

            /SECFIX :: FIX file SECurity on all files, even skipped files.
            /TIMFIX :: FIX file TIMes on all files, even skipped files.

             /PURGE :: delete dest files/dirs that no longer exist in source.
               /MIR :: MIRror a directory tree (equivalent to /E plus /PURGE).

               /MOV :: MOVe files (delete from source after copying).
              /MOVE :: MOVE files AND dirs (delete from source after copying).

     /A+:[RASHCNET] :: add the given Attributes to copied files.
     /A-:[RASHCNET] :: remove the given Attributes from copied files.

            /CREATE :: CREATE directory tree and zero-length files only.
               /FAT :: create destination files using 8.3 FAT file names only.
               /256 :: turn off very long path (> 256 characters) support.

             /MON:n :: MONitor source; run again when more than n changes seen.
             /MOT:m :: MOnitor source; run again in m minutes Time, if changed.

      /RH:hhmm-hhmm :: Run Hours - times when new copies may be started.
                /PF :: check run hours on a Per File (not per pass) basis.

             /IPG:n :: Inter-Packet Gap (ms), to free bandwidth on slow lines.

                 /SL:: copy symbolic links versus the target.
:: File Selection Options :
                 /A :: copy only files with the Archive attribute set.
                 /M :: copy only files with the Archive attribute and reset it.
    /IA:[RASHCNETO] :: Include only files with any of the given Attributes set.
    /XA:[RASHCNETO] :: eXclude files with any of the given Attributes set.

 /XF file [file]... :: eXclude Files matching given names/paths/wildcards.
 /XD dirs [dirs]... :: eXclude Directories matching given names/paths.

                /XC :: eXclude Changed files.
                /XN :: eXclude Newer files.
                /XO :: eXclude Older files.
                /XX :: eXclude eXtra files and directories.
                /XL :: eXclude Lonely files and directories.
                /IS :: Include Same files.
                /IT :: Include Tweaked files.

             /MAX:n :: MAXimum file size - exclude files bigger than n bytes.
             /MIN:n :: MINimum file size - exclude files smaller than n bytes.

          /MAXAGE:n :: MAXimum file AGE - exclude files older than n days/date.
          /MINAGE:n :: MINimum file AGE - exclude files newer than n days/date.
          /MAXLAD:n :: MAXimum Last Access Date - exclude files unused since n.
          /MINLAD:n :: MINimum Last Access Date - exclude files used since n.
                       (If n < 1900 then n = n days, else n = YYYYMMDD date).

                /XJ :: eXclude Junction points. (normally included by default).

               /FFT :: assume FAT File Times (2-second granularity).
               /DST :: compensate for one-hour DST time differences.

               /XJD :: eXclude Junction points for Directories.
               /XJF :: eXclude Junction points for Files.

:: Retry Options :
               /R:n :: number of Retries on failed copies: default 1 million.
               /W:n :: Wait time between retries: default is 30 seconds.

               /REG :: Save /R:n and /W:n in the Registry as default settings.

               /TBD :: wait for sharenames To Be Defined (retry error 67).

:: Logging Options :
                 /L :: List only - don't copy, timestamp or delete any files.
                 /X :: report all eXtra files, not just those selected.
                 /V :: produce Verbose output, showing skipped files.
                /TS :: include source file Time Stamps in the output.
                /FP :: include Full Pathname of files in the output.
             /BYTES :: Print sizes as bytes.

                /NS :: No Size - don't log file sizes.
                /NC :: No Class - don't log file classes.
               /NFL :: No File List - don't log file names.
               /NDL :: No Directory List - don't log directory names.

                /NP :: No Progress - don't display % copied.
               /ETA :: show Estimated Time of Arrival of copied files.

          /LOG:file :: output status to LOG file (overwrite existing log).
         /LOG+:file :: output status to LOG file (append to existing log).

       /UNILOG:file :: output status to LOG file as UNICODE (overwrite existing log).
      /UNILOG+:file :: output status to LOG file as UNICODE (append to existing log).

               /TEE :: output to console window, as well as the log file.

               /NJH :: No Job Header.
               /NJS :: No Job Summary.

           /UNICODE :: output status as UNICODE.

:: Job Options :
       /JOB:jobname :: take parameters from the named JOB file.
      /SAVE:jobname :: SAVE parameters to the named job file
              /QUIT :: QUIT after processing command line (to view parameters).
              /NOSD :: NO Source Directory is specified.
              /NODD :: NO Destination Directory is specified.
                /IF :: Include the following Files.



Windows System Startup and Registry Research Tools

by 20. October 2008 19:06

msconfig (run from Start > Run)




Remote Desktop Connections

by 11. August 2008 16:57

Connecting remotely using %SystemRoot%\System32\mstsc.exe (run with /? for list of command line parameters).

When attempting to connect via RDC, the server will typically only support a fixed number of active connections (in my experience with various Windows servers it is typically 2).  This means that only two different users can be connected at the same time.  Also, when users don’t log off properly (i.e. by closing the client window vs. actually logging off) their session stays connected even though they no longer have a client window open to it.  This is usefull if you want to leave a process running, leave windows open, etc., close your client window and re-connect later to pick up where you left off.  However, the downside is that you will be blocking one of the available connections thus preventing other new sessions.  Should the machine become inaccessible due to too many active connections you have four basic options of recovery (shown below).

  1. Launch "All Programs" > "Administrative Tools" > “Terminal Services Manager” and then expand the "All Listed Servers" treeview on the left pane.  You should see your domain name there, double-click to load list of all available machines.  Find the machine in question and click on it to view the active connections in the right pane.  You can right-click on any of the connections in the right pane and perform several actions such as ("Send Message", "Disconnect","Reset", etc.).  Typically, you will select "Reset" on the connections that are inactive.
  2. mstsc /console” command. This will launch the same Remote Desktop Client you use every day; however, it will connect you in Console Mode. Console Mode means connecting to the server as if you were actually on the server using the server’s keyboard and mouse.  Only one person can be connected in console mode at a time.  Once you get on the machine in Console Mode you can launch “Terminal Service Manager” to view the disconnected sessions and reset them to reclaim the connections as described in option 1 above.
  3. qwinsta /SERVER:servername” command. This display the connections on the machine in question.  You can then run "rwinsta {sessionname | sessionid} /SERVER:servername" command to reset the desired connection.
  4. Method of last resort, get on the physical machine and perform option 1 above.  This is the same as option 1 and 2 other than you need to get on the physical machine.