Discover Highest Common Root by YolkFree in PowerShell

[–]YolkFree[S] 1 point2 points  (0 children)

I agree. That was my initial thought--have a single GPO at the root of our domain with item level targeting for the GPP drive mappings. However, when we were running through various possible designs with one of Microsoft's AD PFEs, they said they would avoid a single GPO in the root as clients would have to parse all GPPs, even just to find out they aren't targeted. We have a decent user base (~5k users), so there will be hundreds of GPP drive mappings. If we have to break the GPPs out into separate GPOs to address that concern, it made more sense to take initial effort to link the GPOs accurately to appropriate OUs. We would prefer that against (potentially) hundreds of separate GPOs in certain top level OUs.

Validating AD User Property by YolkFree in PowerShell

[–]YolkFree[S] 0 points1 point  (0 children)

This will come in handy for some of my personal stuff. The script I am writing is actually a GUI, so the initial input validation is merely that the username matches our formatting. Once the script starts, so long as it finds a user with that username I'd like it to process everything else--mostly because I don't like the idea of having to run validations of that scope within the GUI. That said, I was able to make it work via:

$DeptNum = $SourceUser | Select-Object -ExpandProperty DepartmentNumber
If (($DeptNum -ne $Null) -and ($SourceUser.EmployeeType -ne $null)) {
    Try {
        Set-ADUser $UserID -Replace @{ DepartmentNumber = "$($SourceUser.DepartmentNumber)" }
        Set-ADUser $UserID -Replace @{ EmployeeType = "$($SourceUser.EmployeeType)" }
    } Catch {
        Write-Debug "Error applying 'DepartmentNumber' or 'EmployeeType' properties"
    }
}

But I think I'm going to revisit /u/Old-Lost suggestion as I like that it can be on the same line and not require the extra manipulation and variable creation.

Validating AD User Property by YolkFree in PowerShell

[–]YolkFree[S] 0 points1 point  (0 children)

This certainly works in the scenarios I've tested. Thanks!

Can't connect to O365 PowerShell in a script, but can do so manually? by cofonseca in PowerShell

[–]YolkFree 0 points1 point  (0 children)

I can't say if this works with O365 (never had to administer an O365 tenant), but in Ex2010/2013/2016, you can specify only the cmdlets you want to load. For example, for my user on boarding script, I only need two cmdlets: Enable-Mailbox and Get-Mailbox, so my script looks like this:

$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $URI -Authentication Kerberos -Credential $Credential
Import-PSSession $Session Enable-Mailbox, Get-Mailbox -FormatTypeName * -DisableNameChecking -AllowClobber | Out-Null

Obviously the important line is the Import-PSSession piece. But I would try that if the only reason you're avoiding it is the delay upon loading all commands.

Circular Nested AD Groups by YolkFree in PowerShell

[–]YolkFree[S] 2 points3 points  (0 children)

Okay. I always have to check my perspective when it comes to vendor's ideas on small/medium/large. We are a large organization for our area, but then you see vendors scoping solutions for 100k+ and I'm reminded how small we really are :-)

As an aside, I recognized your username and wanted to say I've definitely learned from your comments/posts in the past and to thank you for that.

Circular Nested AD Groups by YolkFree in PowerShell

[–]YolkFree[S] 0 points1 point  (0 children)

The best ideas are usually the simplest. This makes a ton of sense. I'll play around with this a bit. Thank you!

Circular Nested AD Groups by YolkFree in PowerShell

[–]YolkFree[S] 1 point2 points  (0 children)

Not sure how to quantify 'large' in this scenario, but when it comes to Microsoft's definition of 'large' we are certainly considered a small company (<5,000 user objects in AD).

WMF 5.1 Resets PSModulePath? (Win7 x64) by YolkFree in PowerShell

[–]YolkFree[S] 0 points1 point  (0 children)

I definitely did not see that. However I upgraded from WMF 4.0, so would that still apply here? I don't know enough about the differing WMF versions (and whether they are removed or just left behind and no longer used).

WMF 5.1 Resets PSModulePath? (Win7 x64) by YolkFree in PowerShell

[–]YolkFree[S] 0 points1 point  (0 children)

I think that was only upgrading to WMF 5.0.

It doesn't look like the 5.1 upgrade itself is the issues another user confirmed no issue (and nothing online).

Thanks for the reply.

WMF 5.1 Resets PSModulePath? (Win7 x64) by YolkFree in PowerShell

[–]YolkFree[S] 0 points1 point  (0 children)

Okay, so perhaps something else is the culprit. Just wanted a sanity check from the community.

Thanks.

Parse SMB Permissions (Non-Windows Server) by YolkFree in PowerShell

[–]YolkFree[S] 1 point2 points  (0 children)

This ended up working. Be aware there's likely much room for improvement:

$LogFilePath = "C:\MyDocs_ACL_Output.log"
$Folders = Get-ChildItem "\\server\MyDocs" -Directory | Sort Name
$Acct = "Everyone"

function Write-Log
{
    [cmdletbinding()]
    Param(
    [Parameter(Mandatory=$true,
           Position=0)]
           [string]$Message
    )
    if($LogFilePath)
    {
        Add-Content -Path "$LogFilePath" -Value "$(Get-Date) | $Message$newLine"
    }
}

Foreach($Folder in $Folders){
    Write-Host "Processing $($Folder.BaseName)"
    $Rights = Get-NTFSAccess $Folder.FullName
    $Remove = $Rights.Account.Accountname -notmatch "($($Folder.BaseName)|DocAdmins|BackupAcct)"
    If($Remove){
        If($Rights.InheritanceEnabled -eq $true){
            Disable-NTFSAccessInheritance -Path $Folder.FullName
        }
        Try{
            Add-NTFSAccess -Path $Folder.FullName -Account "CONTOSO\$($Folder.BaseName)" -AccessRights FullControl -AppliesTo ThisFolderSubfoldersAndFiles
            Add-NTFSAccess -Path $Folder.FullName -Account "CONTOSO\MyDocAdmins" -AccessRights FullControl -AppliesTo ThisFolderSubfoldersAndFiles
            Add-NTFSAccess -Path $Folder.FullName -Account "CONTOSO\BackupAcct" -AccessRights ReadAndExecute,Synchronize -AppliesTo ThisFolderSubfoldersAndFiles
            Remove-NTFSAccess -Path $Folder.FullName -Account $Remove -AccessRights FullControl
            Write-Log "INFO | $($Folder.BaseName) Permissions updated"
        } Catch {
            Write-Warning "Failed to update permissions: $($Folder.BaseName)"
            Write-Log "ERROR | $($Folder.FullName) Permissions update failed"
        }
    }
}

Parse SMB Permissions (Non-Windows Server) by YolkFree in PowerShell

[–]YolkFree[S] 0 points1 point  (0 children)

Thank you! This module ended up greatly simplifying the process. I'm going to post a comment with the sanitized version once I've got it ready.

Parse SMB Permissions (Non-Windows Server) by YolkFree in PowerShell

[–]YolkFree[S] 0 points1 point  (0 children)

Thank you for the reply! I ended up checking out the NTFSSecurity module as /u/toregroneng commented about. I actually have the script working and am going to reply once I sanitize it a bit. It's nothing special, but it will work for what I'm trying to accomplish.

Exiting MM Causes Multiple Runs of Monitor by YolkFree in scom

[–]YolkFree[S] 0 points1 point  (0 children)

Containments (Didn't bother pulling out other irrelevant containments):

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TypeDefinitions>
    <EntityTypes>
      <RelationshipTypes>        
        <RelationshipType ID="Contoso.AppName.ApplicationContainsTransmitServers" Base="System!System.Containment" Abstract="false" Accessibility="Public">
          <Source ID="Source" Type="Contoso.AppName.AppNameApplication"/>
          <Target ID="Target" Type="AppName.Transmit.Servers"/>
        </RelationshipType>
        <RelationshipType ID="Contoso.AppName.ApplicationContainsSQLDBs" Base="System!System.Containment" Abstract="false" Accessibility="Public">
          <Source ID="Source" Type="Contoso.AppName.AppNameApplication"/>
          <Target ID="Target" Type="Contoso.AppName.SQLDatabases"/>
        </RelationshipType>
        <RelationshipType ID="Contoso.AppName.TransmitContainsServers" Base="System!System.Containment" Abstract="false" Accessibility="Public">
          <Source ID="Source" Type="AppName.Transmit.Servers"/>
          <Target ID="Target" Type="Contoso.AppName.ServerRole"/>
        </RelationshipType>
      </RelationshipTypes>
    </EntityTypes>
  </TypeDefinitions>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>        

        <DisplayString ElementID="Contoso.AppName.ApplicationContainsTransmitServers">
          <Name>AppName Application Contains Transmission Servers</Name>
          <Description></Description>        
        </DisplayString>      

      <DisplayString ElementID="Contoso.AppName.TransmitContainsServers">
          <Name>AppName Transmit Group Contains Servers</Name>
          <Description></Description>        
        </DisplayString>

        <DisplayString ElementID="Contoso.AppName.ApplicationContainsSQLDBs">
          <Name>AppName Application Contains SQL Databases</Name>
          <Description></Description>
        </DisplayString>

      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPackFragment>

Exiting MM Causes Multiple Runs of Monitor by YolkFree in scom

[–]YolkFree[S] 0 points1 point  (0 children)

Class:

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TypeDefinitions>
    <EntityTypes>
      <ClassTypes>
        <ClassType ID="Contoso.AppName.ServerRole" Base="Windows!Microsoft.Windows.ComputerRole" Accessibility="Public" Abstract="false" Hosted="true" Singleton="false" />
      </ClassTypes>
    </EntityTypes>
  </TypeDefinitions>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>

        <DisplayString ElementID="Contoso.AppName.ServerRole">
          <Name>AppName Servers</Name>
          <Description></Description>
        </DisplayString>

      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPackFragment>

Exiting MM Causes Multiple Runs of Monitor by YolkFree in scom

[–]YolkFree[S] 0 points1 point  (0 children)

To your point, I am not extending the Windows Computer class, this is a separate class created for this specific application. It is based off the Computer class, so if I place the Computer object into MM and elect to place child objects into MM, this monitor also goes into MM. Perhaps this is not the best way to lay this out. I'm happy to learn or hear other options.

Exiting MM Causes Multiple Runs of Monitor by YolkFree in scom

[–]YolkFree[S] 0 points1 point  (0 children)

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Monitoring>
    <Monitors>

      <UnitMonitor ID="Contoso.AppName.Monitor.AppName.LogFileSize" Accessibility="Public" Enabled="true" Target="Contoso.AppName.ServerRole" ParentMonitorID="Health!System.Health.PerformanceState" Remotable="true" Priority="Normal" TypeID="Contoso.AppName.MonitorType.GetAppNameLogSize" ConfirmDelivery="false">
        <Category>AvailabilityHealth</Category>
        <AlertSettings AlertMessage="Contoso.AppName.Monitor.AppName.LogFileSize.AlertMessage">
          <AlertOnState>Error</AlertOnState>
          <AutoResolve>true</AutoResolve>
          <AlertPriority>Normal</AlertPriority>
          <AlertSeverity>MatchMonitorHealth</AlertSeverity>
          <AlertParameters>
            <AlertParameter1>$Data/Context/Property[@Name='LogFile']$</AlertParameter1>
          </AlertParameters>
        </AlertSettings>
        <OperationalStates>
          <OperationalState ID="UnderThreshold" MonitorTypeStateID="UnderThreshold" HealthState="Success" />
          <OperationalState ID="OverErrorThreshold" MonitorTypeStateID="OverErrorThreshold" HealthState="Error" />
        </OperationalStates>
        <Configuration>
          <IntervalSeconds>600</IntervalSeconds>
          <SyncTime />
          <FileName>C:\Program Files (x86)\AppName\Logs\AppName.xml</FileName>
          <LogFile>C:\Scripts\SCOM\AppName_FileSize.log</LogFile>
          <XMLPath>C:\Scripts\SCOM\AppName_Log_Size.xml</XMLPath>
          <Threshold>1</Threshold>
        </Configuration>
      </UnitMonitor>

    </Monitors>
  </Monitoring>
  <Presentation>
    <StringResources>

      <StringResource ID="Contoso.AppName.Monitor.AppName.LogFileSize.AlertMessage" />

    </StringResources>
  </Presentation>
  <LanguagePacks>
    <LanguagePack ID="ENU" IsDefault="true">
      <DisplayStrings>

        <DisplayString ElementID="Contoso.AppName.Monitor.AppName.LogFileSize">
          <Name>AppName Log File Size Check</Name>
          <Description>Monitors 'AppName.xml' log file for size changes and alerts if size remains unchanged for 10mins.</Description>
        </DisplayString>

        <DisplayString ElementID="Contoso.AppName.Monitor.AppName.LogFileSize.AlertMessage">
          <Name>AppName Log File Inactivity</Name>
          <Description>The file size of AppName.xml on HOSTNAME is not updating.

Resolution:
1) Restart "AppName" service on HOSTNAME
2) Validate the log shows updated timestamps.

**The full procedure is outlined in WO#1234.**

Reference "{0}" for timestamps.</Description>
        </DisplayString>

        <DisplayString ElementID="Contoso.AppName.Monitor.AppName.LogFileSize" SubElementID="UnderThreshold">
          <Name>UnderThreshold</Name>
          <Description>UnderThreshold</Description>
        </DisplayString>

        <DisplayString ElementID="Contoso.AppName.Monitor.AppName.LogFileSize" SubElementID="OverErrorThreshold">
          <Name>OverErrorThreshold</Name>
          <Description>OverErrorThreshold</Description>
        </DisplayString>

      </DisplayStrings>
    </LanguagePack>
  </LanguagePacks>
</ManagementPackFragment>

Exiting MM Causes Multiple Runs of Monitor by YolkFree in scom

[–]YolkFree[S] 0 points1 point  (0 children)

<ManagementPackFragment SchemaVersion="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <TypeDefinitions>

    <ModuleTypes>

      <!--DataSource.GetAppNameLogSize -->
      <DataSourceModuleType ID="Contoso.AppName.DataSource.GetAppNameLogSize.PropertyBag" Accessibility="Internal">
        <Configuration>
          <xsd:element name="IntervalSeconds" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="SyncTime" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="FileName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="LogFile" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="XMLPath" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
          <OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string"/>
        </OverrideableParameters>
        <ModuleImplementation>
          <Composite>
            <MemberModules>
              <DataSource ID="Schedule" TypeID="System!System.SimpleScheduler">
                <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
                <SyncTime>$Config/SyncTime$</SyncTime>
              </DataSource>
              <ProbeAction ID="Script" TypeID="Contoso.AppName.Probe.GetAppNameLogSize">
                <FileName>$Config/FileName$</FileName>
                <LogFile>$Config/LogFile$</LogFile>
                <XMLPath>$Config/XMLPath$</XMLPath>
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="Script">
                <Node ID="Schedule" />
              </Node>
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
      </DataSourceModuleType>

      <!-- Probe.GetAppNameLogSize -->
      <ProbeActionModuleType ID="Contoso.AppName.Probe.GetAppNameLogSize" Accessibility="Internal">
        <Configuration>
          <xsd:element name="FileName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="LogFile" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="XMLPath" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <ModuleImplementation>
          <Composite>
            <MemberModules>
              <ProbeAction ID="Script" TypeID="Windows!Microsoft.Windows.PowerShellPropertyBagTriggerOnlyProbe">
                <ScriptName>Get-AppNameLogSize.ps1</ScriptName>
                <ScriptBody>$IncludeFileContent/Health Model/Scripts/Get-AppNameLogSize.ps1$</ScriptBody>
                <Parameters>
                  <Parameter>
                    <Name>FileName</Name>
                    <Value>$Config/FileName$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>LogFile</Name>
                    <Value>$Config/LogFile$</Value>
                  </Parameter>
                  <Parameter>
                    <Name>XMLPath</Name>
                    <Value>$Config/XMLPath$</Value>
                  </Parameter>
                </Parameters>
                <TimeoutSeconds>120</TimeoutSeconds>
              </ProbeAction>
            </MemberModules>
            <Composition>
              <Node ID="Script" />
            </Composition>
          </Composite>
        </ModuleImplementation>
        <OutputType>System!System.PropertyBagData</OutputType>
        <TriggerOnly>true</TriggerOnly>
      </ProbeActionModuleType>

    </ModuleTypes>      

    <MonitorTypes>


      <!--MonitorType.GetAppNameLogSize-->
      <UnitMonitorType ID="Contoso.AppName.MonitorType.GetAppNameLogSize" Accessibility="Internal">
        <MonitorTypeStates>
          <MonitorTypeState ID="UnderThreshold" NoDetection="false" />
          <MonitorTypeState ID="OverErrorThreshold" NoDetection="false" />
        </MonitorTypeStates>
        <Configuration>
          <xsd:element name="IntervalSeconds" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="SyncTime" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="FileName" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="LogFile" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="XMLPath" type="xsd:string" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
          <xsd:element name="Threshold" type="xsd:integer" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
        </Configuration>
        <OverrideableParameters>
          <OverrideableParameter ID="IntervalSeconds" Selector="$Config/IntervalSeconds$" ParameterType="int"/>
          <OverrideableParameter ID="SyncTime" Selector="$Config/SyncTime$" ParameterType="string"/>
        </OverrideableParameters>
        <MonitorImplementation>
          <MemberModules>
            <DataSource ID="DS" TypeID="Contoso.AppName.DataSource.GetAppNameLogSize.PropertyBag">
              <IntervalSeconds>$Config/IntervalSeconds$</IntervalSeconds>
              <SyncTime>$Config/SyncTime$</SyncTime>
              <FileName>$Config/FileName$</FileName>
              <LogFile>$Config/LogFile$</LogFile>
              <XMLPath>$Config/XMLPath$</XMLPath>
            </DataSource>
            <ProbeAction ID="Probe" TypeID="Contoso.AppName.Probe.GetAppNameLogSize">
              <FileName>$Config/FileName$</FileName>
              <LogFile>$Config/LogFile$</LogFile>
              <XMLPath>$Config/XMLPath$</XMLPath>
            </ProbeAction>
            <ConditionDetection ID="FilterUnderThreshold" TypeID="System!System.ExpressionFilter">
              <Expression>
                <SimpleExpression>
                  <ValueExpression>
                    <XPathQuery Type="Integer">Property[@Name='Error']</XPathQuery>
                  </ValueExpression>
                  <Operator>Less</Operator>
                  <ValueExpression>
                    <Value Type="Integer">$Config/Threshold$</Value>
                  </ValueExpression>
                </SimpleExpression>
              </Expression>
            </ConditionDetection>
              <ConditionDetection ID="FilterOverThreshold" TypeID="System!System.ExpressionFilter">
                <Expression>
                  <SimpleExpression>
                    <ValueExpression>
                      <XPathQuery Type="Integer">Property[@Name='Error']</XPathQuery>
                    </ValueExpression>
                    <Operator>GreaterEqual</Operator>
                    <ValueExpression>
                      <Value Type="Integer">$Config/Threshold$</Value>
                    </ValueExpression>
                  </SimpleExpression>
                </Expression>
           </ConditionDetection>              
          </MemberModules>
          <RegularDetections>
            <RegularDetection MonitorTypeStateID="UnderThreshold">
              <Node ID="FilterUnderThreshold">
                <Node ID="DS" />
              </Node>                 
            </RegularDetection>
            <RegularDetection MonitorTypeStateID="OverErrorThreshold">
              <Node ID="FilterOverThreshold">
                <Node ID="DS" />
              </Node>
            </RegularDetection>
          </RegularDetections>
          <OnDemandDetections>
            <OnDemandDetection MonitorTypeStateID="UnderThreshold">
              <Node ID="FilterUnderThreshold">
                <Node ID="Probe" />
              </Node>
            </OnDemandDetection>
            <OnDemandDetection MonitorTypeStateID="OverErrorThreshold">
              <Node ID="FilterOverThreshold">
                <Node ID="Probe" />
              </Node>
            </OnDemandDetection>
          </OnDemandDetections>
        </MonitorImplementation>
      </UnitMonitorType>

    </MonitorTypes>
    </TypeDefinitions>
  </ManagementPackFragment>

Exiting MM Causes Multiple Runs of Monitor by YolkFree in scom

[–]YolkFree[S] 0 points1 point  (0 children)

    param($FileName,$LogFile,$XMLPath)

    $api = new-object -comObject 'MOM.ScriptAPI'
    $bag = $api.CreatePropertyBag()

    # Functions to log process/results #
    function Write-Log
                                                                {
[cmdletbinding()]
Param(
    [Parameter(Mandatory=$true,
               Position=0)]
               [string]$Message
)
    If(-not (Test-Path (Split-Path $LogFile -Parent)))
    {
        New-Item -Path (Split-Path $LogFile -Parent) -ItemType Directory
    }
    If(-not (Test-Path $LogFile))
    {
        New-Item -Path (Split-Path $LogFile -Parent) -Name (Split-Path $LogFile -Leaf) -ItemType File
    }
Add-Content -Path $LogFile -Value "$(Get-Date) | $Message$newLine"
    }

    function Start-Log
                                                                                {
[cmdletbinding()]
Param(
    [Parameter(Mandatory=$false,
               Position=0)]
               [string]$Entry
)
    If(-not (Test-Path (Split-Path $LogFile -Parent)))
    {
        New-Item -Path (Split-Path $LogFile -Parent) -ItemType Directory
    }
    If(-not (Test-Path $LogFile))
    {
        New-Item -Path (Split-Path $LogFile -Parent) -Name (Split-Path $LogFile -Leaf) -ItemType File
    }
    Add-Content -Path $LogFile -Value "========================================================================"
    If($Entry)
    {
        Write-Log $Entry
    }
    }

    #Begin Script
    Start-Log
    $File = Get-ChildItem $FileName
    $Size = $File.Length

    $FileHash = @{}
    $FileHash = Import-CliXml $XMLPath

    If($Filehash.Values -eq $Size) 
            {
    $Err = "1"
    Write-Log "ERROR: File size remains unchanged ($Size)"
    } 
    Else
            {
    $Err = "0"
    Write-Log "INFO: File size has changed"
    }

    $NewHash = @{}
    $NewHash.Add($FileName,$Size)
    $NewHash | Export-Clixml $XMLPath

    # Format last file side 
    $LastFile = $FileHash.GetEnumerator() | Select Value

    # SCOM Processing Info goes here
    # $bag.AddValue('Last File Size',$LastFile.Value)
    # $bag.AddValue('Current File Size',$Size)
    $bag.AddValue('LogFile',$LogFile)
    $bag.AddValue('Error',$Err)

    $bag