Windows – PowerShell – Return Computer Status, IP, OS, etc.

email me

by Gandalf50

 
Param ([switch]$NoWarning,[switch]$Debug)

If ($Debug) {
    #enable debug messages if -debug is specified
    $debugPreference="Continue"
}

If ($NoWarning) {
    #turn off warning messages
    $WarningPreference="SilentlyContinue"
}

function Ping-Host {
  Param([string]$computername=$(Throw "You must specify a computername."))
  
  Write-Debug "In Ping-Host function"
  
  $query="Select * from Win32_PingStatus where address='$computername'"
  
  $wmi=Get-WmiObject -query $query
  write $wmi
}

function Get-OS {
  Param([string]$computername=$(Throw "You must specify a computername."))
  Write-Debug "In Get-OS Function"
  $wmi=Get-WmiObject Win32_OperatingSystem -computername $computername -ea stop
  
  write $wmi

}


#Generated Form Function
function GenerateForm {

#region Import the Assemblies
Write-Debug "Loading Assemblies"
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
#endregion

#region Generated Form Objects
Write-Debug "Creating form objects"
$form1 = New-Object System.Windows.Forms.Form
$lblRefreshInterval = New-Object System.Windows.Forms.Label
$numInterval = New-Object System.Windows.Forms.NumericUpDown
$btnQuit = New-Object System.Windows.Forms.Button
$btnGo = New-Object System.Windows.Forms.Button
$dataGridView = New-Object System.Windows.Forms.DataGridView
$label2 = New-Object System.Windows.Forms.Label
$statusBar = New-Object System.Windows.Forms.StatusBar
$txtComputerList = New-Object System.Windows.Forms.TextBox
$timer1 = New-Object System.Windows.Forms.Timer
#endregion Generated Form Objects

#----------------------------------------------
#Generated Event Script Blocks
#----------------------------------------------

$LaunchCompMgmt= 
{
    #only launch computer management if a cell in the Computername 
    #column was selected.
    $c=$dataGridView.CurrentCell.columnindex
    $colHeader=$dataGridView.columns[$c].name
    if ($colHeader -eq "Computername") {
        $computer=$dataGridView.CurrentCell.Value
        Write-Debug ("Launch computer management for {0}" -f $computer.toUpper())
        compmgmt.msc /computer:$computer
    }
} #end Launch Computer Management script block

$GetStatus= 
{

 Trap {
    	Write-Debug "Error trapped in GetStatus script block"
    	Write-Warning $_.Exception.message
        Continue
    }
    
    #stop the timer while data is refreshed
    Write-Debug "Stop the timer"
    $timer1.stop()

    Write-Debug ("Getting content from {0}" -f $txtComputerlist.Text)
    if ($computers) {Clear-Variable computers}
    
    #clear the table
    $dataGridView.DataSource=$Null
    
    $computers=Get-Content $txtComputerList.Text -ea stop | sort 
    
    if ($computers) {
       
        $statusBar.Text = ("Querying computers from {0}" -f $txtComputerList.Text)
        $form1.Refresh
        
        #create an array for griddata
        Write-Debug "Create `$griddata"
        $griddata=@()
        #create a custom object
        
        foreach ($computer in $computers) {
          Write-Debug "Pinging $computer"
          $statusBar.Text=("Pinging {0}" -f $computer.toUpper())
          Write-Debug "Creating `$obj"
          $obj=New-Object PSobject
          Write-Debug "Adding Computername property"
          $obj | Add-Member Noteproperty Computername $computer.ToUpper()
          
          #ping the computer
          if ($pingResult) {
            #clear PingResult if it has a left over value
            Clear-Variable pingResult
            }
          $pingResult=Ping-Host $computer
          Write-Debug "Pinged status code is $($pingResult.Statuscode)"
      
          if ($pingResult.StatusCode -eq 0) {
               
               $obj | Add-Member Noteproperty Pinged "Yes"
               Write-Debug "Adding $($pingresult.ProtocolAddress)"
               $obj | Add-Member Noteproperty IP $pingResult.ProtocolAddress
               
               #get remaining information via WMI
               Trap {
                #define a trap to handle any WMI errors
                Write-Warning ("There was a problem with {0}" -f $computer.toUpper())
                Write-Warning $_.Exception.GetType().FullName
                Write-Warning $_.Exception.message
                Continue
                }
               		
                if ($os) {
                    #clear OS if it has a left over value
                    Clear-Variable os
                }
               $os=Get-OS $computer
               if ($os) {
                   $lastboot=$os.ConvertToDateTime($os.lastbootuptime)
                   Write-Debug "Adding $lastboot"
                   $uptime=((get-date) - ($os.ConvertToDateTime($os.lastbootuptime))).tostring()
                   Write-Debug "Adding $uptime"
                   $osname=$os.Caption
                   Write-Debug "Adding $osname"
                   $servicepack=$os.CSDVersion
                   Write-Debug "Adding $servicepack"
                   
                   $obj | Add-Member Noteproperty OS $osname
                   $obj | Add-Member Noteproperty ServicePack $servicepack
                   $obj | Add-Member Noteproperty Uptime $uptime
                   $obj | Add-Member Noteproperty LastBoot $lastboot
               }
               else {
               Write-Debug "Setting properties to N/A"
                   $obj | Add-Member Noteproperty OS "N/A"
                   $obj | Add-Member Noteproperty ServicePack "N/A"
                   $obj | Add-Member Noteproperty Uptime "N/A"
                   $obj | Add-Member Noteproperty LastBoot "N/A"
               }
          }
          else {
                Write-Debug "Ping failed"
                Write-Debug "Setting properties to N/A"

               $obj | Add-Member Noteproperty Pinged "No"
               $obj | Add-Member Noteproperty IP "N/A"
               $obj | Add-Member Noteproperty OS "N/A"
               $obj | Add-Member Noteproperty ServicePack "N/A"
               $obj | Add-Member Noteproperty Uptime "N/A"
               $obj | Add-Member Noteproperty LastBoot "N/A"
          }
        
        	#Add the object to griddata
            	Write-Debug "Adding `$obj to `$griddata"
            	$griddata+=$obj

		
        } #end foreach
        
        Write-Debug "Creating ArrayList"   
        $array= New-Object System.Collections.ArrayList
        
        Write-Debug "Adding `$griddata to `$arry"
        $array.AddRange($griddata)
        $DataGridView.DataSource = $array
        #find unpingable computer rows
        Write-Debug "Searching for non-pingable computers"
        $c=$dataGridView.RowCount
        for ($x=0;$x -lt $c;$x++) {
            for ($y=0;$y -lt $dataGridView.Rows[$x].Cells.Count;$y++) {
                $value = $dataGridView.Rows[$x].Cells[$y].Value
                if ($value -eq "No") {
                #if Pinged cell = No change the row font color
                Write-Debug "Changing color on row $x"
                $dataGridView.rows[$x].DefaultCellStyle.Forecolor=[System.Drawing.Color]::FromArgb(255,255,0,0)
                }
            }
        }
        Write-Debug "Setting status bar text"
        $statusBar.Text=("Ready. Last updated {0}" -f (Get-Date))

    }
    else {
        Write-Debug "Setting status bar text"
        $statusBar.Text=("Failed to find {0}" -f $txtComputerList.text)
    }
   
   #set the timer interval
    $interval=$numInterval.value -as [int]
    Write-Debug "Interval is $interval"
    #interval must be in milliseconds
    $timer1.Interval = ($interval * 60000) #1 minute time interval
    Write-Debug ("Timer interval calculated at {0} milliseconds" -f $timer1.Interval )
    #start the timer
    Write-Debug "Starting timer"
    $timer1.Start()
    
    Write-Debug "Refresh form"
    $form1.Refresh()
   
} #End GetStatus scriptblock

$Quit= 
{
    Write-Debug "closing the form"
    $form1.Close()
} #End Quit scriptblock

#----------------------------------------------
#region Generated Form Code
$form1.Name = 'form1'
$form1.Text = 'Display Computer Status'
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 890
$System_Drawing_Size.Height = 359
$form1.ClientSize = $System_Drawing_Size
$form1.StartPosition = 1
$form1.BackColor = [System.Drawing.Color]::FromArgb(255,185,209,234)

$lblRefreshInterval.Text = 'Refresh Interval (min)'

$lblRefreshInterval.DataBindings.DefaultDataSourceUpdateMode = 0
$lblRefreshInterval.TabIndex = 10
$lblRefreshInterval.TextAlign = 64
#$lblRefreshInterval.Anchor = 9
$lblRefreshInterval.Name = 'lblRefreshInterval'
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 128
$System_Drawing_Size.Height = 23
$lblRefreshInterval.Size = $System_Drawing_Size
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 440
$System_Drawing_Point.Y = 28
$lblRefreshInterval.Location = $System_Drawing_Point

$form1.Controls.Add($lblRefreshInterval)

#$numInterval.Anchor = 9
$numInterval.DataBindings.DefaultDataSourceUpdateMode = 0
$numInterval.Name = 'numInterval'
$numInterval.Value = 10
$numInterval.TabIndex = 9
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 51
$System_Drawing_Size.Height = 20
$numInterval.Size = $System_Drawing_Size
$numInterval.Maximum = 60
$numInterval.Minimum = 1
$numInterval.Increment = 2
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 575
$System_Drawing_Point.Y = 30
$numInterval.Location = $System_Drawing_Point
# $numInterval.add_ValueChanged($GetStatus)

$form1.Controls.Add($numInterval)


$btnQuit.UseVisualStyleBackColor = $True
$btnQuit.Text = 'Close'

$btnQuit.DataBindings.DefaultDataSourceUpdateMode = 0
$btnQuit.TabIndex = 2
$btnQuit.Name = 'btnQuit'
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 75
$System_Drawing_Size.Height = 23
$btnQuit.Size = $System_Drawing_Size
#$btnQuit.Anchor = 9
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 341
$System_Drawing_Point.Y = 30
$btnQuit.Location = $System_Drawing_Point
$btnQuit.add_Click($Quit)

$form1.Controls.Add($btnQuit)


$btnGo.UseVisualStyleBackColor = $True
$btnGo.Text = 'Get Status'

$btnGo.DataBindings.DefaultDataSourceUpdateMode = 0
$btnGo.TabIndex = 1
$btnGo.Name = 'btnGo'
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 75
$System_Drawing_Size.Height = 23
$btnGo.Size = $System_Drawing_Size
#$btnGo.Anchor = 9
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 233
$System_Drawing_Point.Y = 31
$btnGo.Location = $System_Drawing_Point
$btnGo.add_Click($GetStatus)

$form1.Controls.Add($btnGo)

$dataGridView.RowTemplate.DefaultCellStyle.ForeColor = [System.Drawing.Color]::FromArgb(255,0,128,0)
$dataGridView.Name = 'dataGridView'
$dataGridView.DataBindings.DefaultDataSourceUpdateMode = 0
$dataGridView.ReadOnly = $True
$dataGridView.AllowUserToDeleteRows = $False
$dataGridView.RowHeadersVisible = $False
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 870
$System_Drawing_Size.Height = 260
$dataGridView.Size = $System_Drawing_Size
$dataGridView.TabIndex = 8
$dataGridView.Anchor = 15
$dataGridView.AutoSizeColumnsMode = 16



$dataGridView.AllowUserToAddRows = $False
$dataGridView.ColumnHeadersHeightSizeMode = 2
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 13
$System_Drawing_Point.Y = 70
$dataGridView.Location = $System_Drawing_Point
$dataGridView.AllowUserToOrderColumns = $True
$dataGridView.add_CellContentDoubleClick($LaunchCompMgmt)
#$dataGridView.AutoResizeColumns([System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells]::AllCells)
#$DataGridViewAutoSizeColumnsMode.AllCells

$form1.Controls.Add($dataGridView)

$label2.Text = 'Enter the name and path of a text file with your list of computer names: (One name per line)'

$label2.DataBindings.DefaultDataSourceUpdateMode = 0
$label2.TabIndex = 7
$label2.Name = 'label2'
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 490
$System_Drawing_Size.Height = 23
$label2.Size = $System_Drawing_Size
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 7
$label2.Location = $System_Drawing_Point

$form1.Controls.Add($label2)

$statusBar.Name = 'statusBar'
$statusBar.DataBindings.DefaultDataSourceUpdateMode = 0
$statusBar.TabIndex = 4
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 428
$System_Drawing_Size.Height = 22
$statusBar.Size = $System_Drawing_Size
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 0
$System_Drawing_Point.Y = 337
$statusBar.Location = $System_Drawing_Point
$statusBar.Text = 'Ready'

$form1.Controls.Add($statusBar)

$txtComputerList.Text = 'c:\computers.txt'
$txtComputerList.Name = 'txtComputerList'
$txtComputerList.TabIndex = 0
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 198
$System_Drawing_Size.Height = 20
$txtComputerList.Size = $System_Drawing_Size
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 13
$System_Drawing_Point.Y = 33
$txtComputerList.Location = $System_Drawing_Point
$txtComputerList.DataBindings.DefaultDataSourceUpdateMode = 0

$form1.Controls.Add($txtComputerList)


#endregion Generated Form Code

Write-Debug "Adding script block to timer"
#add the script block to execute when the timer interval expires
$timer1.add_Tick($GetStatus)

#Show the Form
Write-Debug "ShowDialog()"
$form1.ShowDialog()| Out-Null

} #End Function

#Call the Function
Write-Debug "Call GenerateForm"
GenerateForm


Windows – PowerShell – Return Installed Applications

email me


$CN = "lab-pc1"


Function Get-OSCInstalledApplication
{
    [CmdletBinding(DefaultParameterSetName='SinglePoint')]
    Param
    (
        [Parameter(Mandatory=$true, Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="SinglePoint")]
        [Alias('CName')][String[]]$ComputerName,
        [Parameter(Mandatory=$true, Position=0, ParameterSetName="MultiplePoint")]
        [Alias('CNPath')][String]$ComputerFilePath
    )
    
    If($ComputerName)
    {
        Foreach($CN in $ComputerName)
        {
            #test compter connectivity
            $PingResult = Test-Connection -ComputerName $CN -Count 1 -Quiet
            If($PingResult)
            {
                FindInstalledApplicationInfo -ComputerName $CN
            }
            Else
            {
                Write-Warning "Failed to connect to computer '$ComputerName'."
            }
        }
    }

    If($ComputerFilePath)
    {
        $ComputerName = (Import-Csv -Path $ComputerFilePath).ComputerName

        Foreach($CN in $ComputerName)
        {
            FindInstalledApplicationInfo -ComputerName $CN
        }
    }
}

Function FindInstalledApplicationInfo($ComputerName)
{
    $Objs = @()
    $RegKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*"
    
    $InstalledAppsInfos = Get-ItemProperty -Path $RegKey

    Foreach($InstalledAppsInfo in $InstalledAppsInfos)
    {
        $Obj = [PSCustomObject]@{Computer=$ComputerName;
                                 DisplayName = $InstalledAppsInfo.DisplayName;
                                 DisplayVersion = $InstalledAppsInfo.DisplayVersion;
                                 Publisher = $InstalledAppsInfo.Publisher}
        $Objs += $Obj
    }
    $Objs | Where-Object { $_.DisplayName } 
}


clear-host

$PingResult = Test-Connection -ComputerName $CN -Count 1 -Quiet 
        If($PingResult) 
        { 
            FindInstalledApplicationInfo -ComputerName $CN 
        } 
        Else 
        { 
            Write-Warning "Failed to connect to computer '$ComputerName'." 
        } 

SCCM – Windows 10 Upgrade – Error code 0x8007000d

email me

This error is related to the Windows Updates service, a service that the Windows 10 upgrade is heavily reliant upon. To repair the service, and clear out temp files and problems, run the following:

 

%windir%\system32\CompatTelRunner.exe -m:appraiser.dll -f:DoScheduledTelemetryRun ent

net stop bits

net stop wuauserv

net stop appidsvc

net stop cryptsvc

Del “%ALLUSERSPROFILE%\Application Data\Microsoft\Network\Downloader\qmgr*.dat

cd /d %windir%\system32

regsvr32.exe urlmon.dll

regsvr32.exe mshtml.dll

regsvr32.exe shdocvw.dll

regsvr32.exe browseui.dll

regsvr32.exe jscript.dll

regsvr32.exe vbscript.dll

regsvr32.exe scrrun.dll

regsvr32.exe msxml.dll

regsvr32.exe msxml3.dll

regsvr32.exe msxml6.dll

regsvr32.exe actxprxy.dll

regsvr32.exe softpub.dll

regsvr32.exe wintrust.dll

regsvr32.exe dssenh.dll

regsvr32.exe rsaenh.dll

regsvr32.exe gpkcsp.dll

regsvr32.exe sccbase.dll

regsvr32.exe slbcsp.dll

regsvr32.exe cryptdlg.dll

regsvr32.exe oleaut32.dll

regsvr32.exe ole32.dll

regsvr32.exe shell32.dll

regsvr32.exe initpki.dll

regsvr32.exe wuapi.dll

regsvr32.exe wuaueng.dll

regsvr32.exe wuaueng1.dll

regsvr32.exe wucltui.dll

regsvr32.exe wups.dll

regsvr32.exe wups2.dll

regsvr32.exe wuweb.dll

regsvr32.exe qmgr.dll

regsvr32.exe qmgrprxy.dll

regsvr32.exe wucltux.dll

regsvr32.exe muweb.dll

regsvr32.exe wuwebv.dll

netsh winsock reset

netsh winhttp reset proxy

sfc /scannow

Reboot computer

Test Windows Updates: Access the the Control Panel Windows Updates applet, and select Check for Updates/Install Updates.

 

Notes

If the OS is already Windows 10, try this

WSReset.exe
dism /online /cleanup-image /restorehealth
dism /online /cleanup-image /StartComponentCleanup
sfc /scannow

powershell

Get-AppXPackage -AllUsers |Where-Object {$_.InstallLocation -like “*SystemApps*”} | Foreach {Add-AppxPackage -DisableDevelopmentMode -Register “$($_.InstallLocation)\AppXManifest.xml”}

Windows – Perfmon not working

email me

My notes during a troubleshooting session for the Performance Monitor. Maybe they’ll be helpful to you.

Before trying anything beyond Disabling the Firewall and checking to make sure you have an account to access the machine:

Launch perfmon as an admin.
Remove all counters.
Add a new counter.
Select remote computer.

 
Then, order of troubleshooting…

 

START SERVICES
—————————-

Remote Procedure Call (RPC)
Remote Registry
WMI Performance Adapter
Performance Counter DLL Host
Performance Logs and Alerts
Remote Procedure Call (RPC) Locator

 

REG KEYS
—————————-

Change reg key permission on Perflib
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib.
‘Local Service’ with ‘Full control’

Add reg key
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\LanmanWorkstation\Parameters
AllowInsecureGuestAuth REG_DWORD to 1

Delete reg key ‘SMBv1’ from
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\LanmanWorkstation\Parameters

Delete reg key ‘EnableSecuritySignature’ from
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\LanmanWorkstation\Parameters


NETWORK

—————————-

Turn on sharing so anyone with network access can read and write files


USERS AND GROUPS

—————————-

Add Everyone to ‘Performance Log Users’
Add Everyone to ‘Performance Monitor Users’

Enable Guest account

 

GROUP POLICY
—————————-

Add ‘Everyone’
The “Allow log on locally” setting specifies the users or groups that are allowed to log into the local computer. This policy can be found in Computer Configuration > Security Settings > Local Policies > User Rights Assignment > Allow log on locally

 

REBUILDING COUNTERS
—————————-

cd c:\windows\system32
lodctr /R
cd c:\windows\sysWOW64
lodctr /R
WINMGMT.EXE /RESYNCPERF
restart machine

 

References

https://support.microsoft.com/en-us/help/2554336/how-to-manually-rebuild-performance-counters-for-windows-server-2008-6

https://support.microsoft.com/en-us/help/300956/how-to-manually-rebuild-performance-counter-library-values

http://mvolo.com/troubleshooting-performance-counter-problems-with-perfmon-and-a-debugger/

 

Notes

Error: The performance counter ‘# result objects in memory’ was not found.
Fix: LODCTR /R

 

PowerShell – Verify if Device is Connected

email me

This will check to see if a device is connected to computer

clear-host

# list out all devices - just for troubleshooting purposes
Get-PnpDevice -PresentOnly

# which device to test
$TestDevice = "Bluetooth"

# test device
If (Get-PnpDevice -PresentOnly -FriendlyName $TestDevice) {write-host "TRUE"} Else {Write-host "FALSE"} -silentlycontinue


Notes

$ErrorActionPreference = ‘Stop’
$ErrorActionPreference= ‘silentlycontinue’

try
{
Main code
}
catch
{
Error handling
}

more…

PowerShell – View Objects of Processes

email me

Screenshot

 

Code

$processName = "explorer.exe"

Set-StrictMode -Version 3

Add-Type -Assembly System.Windows.Forms

$inputObject = dir variable:\* -Exclude InputObject,Args |
    Where-Object {
        $_.Value -and
        ($_.Value.GetType() -eq $processName.GetType()) -and
        ($_.Value.GetHashCode() -eq $processName.GetHashCode())
}

$inputObject = $inputObject| % Name | Select -First 1

if(-not $inputObject)
{
    $inputObject = "InputObject"
}

function PopulateNode($node, $object)
{
    if(-not $object) { return }

    if([System.Management.Automation.LanguagePrimitives]::GetEnumerator($object))
    {
 
        $count = 0

        $isOnlyEnumerable = $object.GetHashCode() -eq $object[0].GetHashCode()
        

        foreach($childObjectValue in $object)
        {            
            $newChildNode = New-Object Windows.Forms.TreeNode
            $newChildNode.Text = "$($node.Name)[$count] = $childObjectValue : " + $childObjectValue.GetType()
                     
            if($isOnlyEnumerable)
            {
                $newChildNode.Name = "@"
            }

            $newChildNode.Name += "[$count]"
            $null = $node.Nodes.Add($newChildNode)               
                        
            AddPlaceholderIfRequired $newChildNode $childObjectValue

            $count++
        }
    }
    else
    {
        
        foreach($child in $object.PSObject.Properties)
        {
        
            $childObject = $child.Value
            $childObjectType = $null
            if($childObject)
            {
                $childObjectType = $childObject.GetType()
            }

            $childNode = New-Object Windows.Forms.TreeNode
            $childNode.Text = $child.Name + " = $childObject : $childObjectType"
            $childNode.Name = $child.Name
            $null = $node.Nodes.Add($childNode)

            AddPlaceholderIfRequired $childNode $childObject
        }
    }
}

function AddPlaceholderIfRequired($node, $object)
{
    if(-not $object) { return }

    if([System.Management.Automation.LanguagePrimitives]::GetEnumerator($object) -or
        @($object.PSObject.Properties))
    {
        $null = $node.Nodes.Add( (New-Object Windows.Forms.TreeNode "...") )
    }
}

function OnAfterSelect
{
    param($Sender, $processTreeEventArgs)

    $nodeSelected = $Sender.SelectedNode

    $nodePath = GetPathForNode $nodeSelected

    $resultObject = Invoke-Expression $nodePath
    $output.Text = $nodePath

    if($resultObject)
    {
        $members = Get-Member -InputObject $resultObject | Out-String       
        $output.Text += "`n" + $members
    }
}


function OnBeforeExpand
{
    param($Sender, $processTreeCancelEventArgs)

    $selectedNode = $processTreeCancelEventArgs.Node

    if($selectedNode.FirstNode -and
        ($selectedNode.FirstNode.Text -eq "..."))
    {
        $selectedNode.Nodes.Clear()
    }
    else
    {
        return
    }

    $nodePath = GetPathForNode $selectedNode 

    Invoke-Expression "`$resultObject = $nodePath"

    PopulateNode $selectedNode $resultObject
}

function OnKeyPress
{
    param($Sender, $KeyPressEventArgs)

    if($KeyPressEventArgs.KeyChar -eq 3)
    {
        $KeyPressEventArgs.Handled = $true

        $node = $Sender.SelectedNode
        $nodePath = GetPathForNode $node
        [System.Windows.Forms.Clipboard]::SetText($nodePath)

        $winform.Close()
    }
}

function GetPathForNode
{
    param($Node)

    $nodeElements = @()

    while($Node)
    {
        $nodeElements = ,$Node + $nodeElements
        $Node = $Node.Parent
    }

    $nodePath = ""
    foreach($Node in $nodeElements)
    {
        $nodeName = $Node.Name

        if($nodeName.StartsWith('@'))
        {
            $nodeName = $nodeName.Substring(1)
            $nodePath = "@(" + $nodePath + ")"
        }
        elseif($nodeName.StartsWith('['))
        {

        }
        elseif($nodePath)
        {
            $nodePath += "."
        }

        $nodePath += $nodeName
    }

    $nodePath
}

$processTree = New-Object Windows.Forms.TreeView
$processTree.Dock = "Top"
$processTree.Height = 200
$processTree.PathSeparator = "."
$processTree.Add_AfterSelect( { OnAfterSelect @args } )
$processTree.Add_BeforeExpand( { OnBeforeExpand @args } )
$processTree.Add_KeyPress( { OnKeyPress @args } )

$output = New-Object System.Windows.Forms.TextBox
$output.Multiline = $true
$output.ScrollBars = "Vertical"
$output.Font = "Calibri"
$output.Dock = "Top"
$output.Height = 600

$root = New-Object Windows.Forms.TreeNode
$root.Text = "$processName : " + $processName.GetType()
$root.Name = '$' + $inputObject
$root.Expand()
$null = $processTree.Nodes.Add($root)

PopulateNode $root $processName

$winform = New-Object Windows.Forms.Form
$winform.Text = "Browsing " + $root.Text
$winform.Width = 1100
$winform.Height = 800
$winform.Controls.Add($output)
$winform.Controls.Add($processTree)
$null = $winform.ShowDialog()
$winform.Dispose()

Python – ICSplit – Split Google Calendar File

email me

Split .ics files into smaller ones for import into Google Calendar, which only supports files less than 1 MB.

 

Source File

https://files.pythonhosted.org/packages/c3/99/539170da786a51936bca8cf6b8998a6616a2aff7827174bba15985da2a5c/icssplit-1.0.0.tar.gz

https://github.com/beorn/icssplit

Python

 

Command

icssplit “path\ICS.ics” “path\out.ics” –maxsize=50000

 

Output

INFO:icssplit:parsing C:\Program Files\Python363\ICS.ics and splitting into files of maxsize=50000
INFO:icssplit:parsed 590 events
INFO:icssplit:writing C:\Program Files\Python363\out.ics-0.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-1.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-2.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-3.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-4.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-5.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-6.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-7.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-8.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-9.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-10.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-11.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-12.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-13.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-14.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-15.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-16.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-17.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-18.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-19.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-20.ics
INFO:icssplit:writing C:\Program Files\Python363\out.ics-21.ics

Screenshot

 

Notes

Installation: setup.py install

NOTE Make sure the ICS file is saved as ANSI.

 

Export Calendar

  1. Select the Settings button from the top right of the page.
  2. Choose Settings when the menu shows.
  3. Open the Calendars tab.
  4. At the bottom of the My Calendars section, choose Export calendars to save every calendar to the ICS format.

To export just one calendar from Google Calendar, click or tap on the calendar from this page and then use the Export this calendar link from the bottom of the next page.

 

 

SCCM – Install Agent on Workgroup Computer

email me

These are the options I used to install the SCCM agent on Workgroup or Azure AD computers

ccmsetup.exe /source:PathToFolder:\SCCM /NATIVE SMSSIGNCERT=PathToFolder:\SCCM\SCCM_WORKGROUP.cer /skipprereq:vcredist_x86.exe /UsePKICert /NoCRLCheck FSP=dmz.domain.com CCMALWAYSINF=1 CCMFIRSTCERT=1 CCMHOSTNAME=dmz.domain.com DNSSUFFIX=domain.com SMSSITECODE=ABC

PKI – CES/CEP – Enrollment Policy

email me

These are the enrollment policy reg keys taken from a reference machine. You basically set up a reference computer using the Manage Enrollment Policies (in mmc, Add certificates, Computer account. And then…Personal, Certificates, All Tasks, Advanced Operations—set up the enrollment policy), export those reg keys, and then automate the import on your client machines.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\PolicyServers]
@=””
“Flags”=dword:00000000
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\PolicyServers\54317f2ebe81a09c15eeb976a6cead1b98353dff]
“URL”=”https://server.external.com/ADPolicyProvider_CEP_UsernamePassword/service.svc/CEP”
“PolicyID”=”{2BEEB86C-F2C8-8C63-796C-0B593C1F6BA5}”
“FriendlyName”=”DOMAIN.COM”
“Flags”=dword:00000020
“AuthFlags”=dword:00000004
“Cost”=dword:7ffffffd

 

Notes

Enable auto enrollment renewal

“Flags”=dword:00000032

 

Delete existing enrollment server URL

certutil –config “{CA Config String}” –enrollmentServerURL https://server.external.com/CA1_CES_UsernamePassword/service.svc/CES delete


To add the enrollment service URI to the CA Enrollment Services in AD

certutil –config “{cahostname.domain.com}\{caname}” –enrollmentServerURL https://server.external.com/Domain-CA_CES_UsernamePassword/service.svc/CES

 

To display CA Enrollment Services object attributes (including the enrollment service URI)

certutil –adca



To display enrollment policy data including general certificate enrollment web service configuration details

certutil –policy



Display existing enrollment server URI’s

certutil –config “{CA Config String}” –enrollmentServerURL

PKI – Autogenerate INF

email me

When submitting a cert request to a certificate authority, to automate this process, you’re going to need an INF. This is how you create that file

echo [NewRequest] > SCCM_WORKGROUP.INF
echo Subject=”CN=%computername%” >> SCCM_WORKGROUP.INF
echo Exportable=TRUE >> SCCM_WORKGROUP.INF
echo KeyLength=1024 >> SCCM_WORKGROUP.INF
echo KeySpec=1 >> SCCM_WORKGROUP.INF
echo KeyUsage=0xA0 >> SCCM_WORKGROUP.INF
echo ProviderName=”Microsoft RSA SChannel Cryptographic Provider” >> SCCM_WORKGROUP.INF
echo ProviderType=12 >> SCCM_WORKGROUP.INF
echo RequestType=PKCS10 >> SCCM_WORKGROUP.INF
echo MachineKeySet=TRUE >> SCCM_WORKGROUP.INF
echo [RequestAttributes] >> SCCM_WORKGROUP.INF
echo SAN=%computername% >> SCCM_WORKGROUP.INF

IDEA You can use PowerShell or another scripting language to create the INF. Just make sure the CN=EnvironmentalVariable for the computer name and SAN.

Notes

Batch – Return Serial Number of Certificate.cer File