SCCM – Windows 10 Upgrade Return Codes

email me

Return Codes

0xC1900101 – 0x20004 –
Causes: This is generally caused by out-of-date drivers.
Possible Solutions: Uninstall antivirus applications/ Remove all unused SATA devices/ Remove all unused devices and drivers/Update drivers.

0xC1900101 – 0x2000C –
Cause: This is generally caused by out-of-date drivers.
Possible Solution: Disconnect all devices that are connected to the system, except for the mouse, keyboard and display/ Contact your hardware vendor to obtain updated device drivers/ Ensure that “Download and install updates (recommended)” is accepted at the start of the upgrade process.

0xC1900101 – 0x20017 –
Cause: Windows was not able to migrate the driver, resulting in a rollback of the operating system.
Possible Solution: Ensure that all the drivers are updated/Open the Setuperr.log and Setupact.log files in the %windir%\Panther directory, and then locate the problem drivers/ Update or uninstall the problem drivers.

0xC1900101 – 0x30018 –
Cause: A device driver has stopped responding to setup.exe during the upgrade process.
Possible Solution: Disconnect all devices that are connected to the system, except for the mouse, keyboard and display/ Contact your hardware vendor to obtain updated device drivers/ Ensure that “Download and install updates (recommended is accepted at the start of the upgrade process.

0xC1900101 – 0x3000D –
Cause: This can occur due to a problem with a display driver.
Possible Solution: Disconnect all devices that are connected to the system, except for the mouse, keyboard and display, and update or uninstall the display driver.

0xC1900101 – 0x4000D –
Cause – A rollback occurred due to a driver configuration issue. Possible Solution: Try changing video adapters.,Make sure you have enough disk space., Disable BIOS memory options such as caching or shadowing..

0xC1900101 – 0x40017 –
Cause – This is usually caused by a faulty driver. antivirus filter drivers or encryption drivers,
Possible Solution: Clean boot into Windows, and then attempt the upgrade to Windows 10. Make sure you select the option to “Download and install updates (recommended).

800704B8 – 0x3001A –
Cause: An extended error has occurred during the first boot phase.
Possible Solution: Disable or uninstall non-Microsoft antivirus applications, disconnect all unnecessary devices, and perform a clean boot.

8007042B – 0x4000D –
Cause: This issue can occur due to file system, application, or driver issues.
Possible Solution: Analyze log files in order to determine the file, application, or driver that is not able to be migrated/Disconnect, update, remove, or replace the device or object.

8007001F – 0x4000D –
Cause: General failure, a device attached to the system is not functioning
Possible Solution: Analyze log files in order to determine the device that is not functioning properly/ Disconnect, update, or replace the device.

8007042B – 0x4001E –
Cause: The installation failed during the second boot phase while attempting the PRE_OOBE operation.
Possible Solution: This error has more than one possible cause/ Attempt quick fixes, and if not successful analyze log files in order to determine the problem and solution.

0xC1800118 –
See Steps to resolve error 0xC1800118 for information.

0xC1900200 –
Ensure the system you are trying to upgrade meets the minimum system requirements. See Windows 10 specifications for information.

0x80090011 –
Contact your hardware vendor and get all the device drivers updated. It is recommended to have an active internet connection during upgrade process.
Ensure that “Download and install updates (recommended)” is accepted at the start of the upgrade process.

0xC7700112 –
This issue is resolved in the latest version of Upgrade Assistant.
Ensure that “Download and install updates (recommended)” is accepted at the start of the upgrade process.

0x80190001 –
To resolve this issue, download and run the media creation tool.

0x80246007 –
Attempt other methods of upgrading the operating system. download and run the media creation tool. See Download windows 10.

0xC1900201 –
Contact the hardware vendor to get the latest updates.

0x80240017 –
Administrative policies enforced by your organization might be preventing the upgrade. Contact your IT administrator.

0x80070020 –
Use the MSCONFIG tool to perform a clean boot on the machine and then try to perform the update again. For more information, see How to perform a clean boot in Windows.

0x80070522 –
Ensure that you have signed in as a local administrator or have local administrator privileges.

0xC1900107 –
Reboot the device and run setup again. If restarting device does not resolve the issue, then use the Disk Cleanup utility and cleanup the temporary as well as the System files. For more information, see Disk cleanup in Windows 10.

0xC1900209 –
Incompatible software is blocking the upgrade process. Uninstall the application and try the upgrade again. See Windows 10 Pre-Upgrade Validation using SETUP.EXE for more information. You can also download the Windows Assessment and Deployment Kit (ADK) for Windows 10 and install Application Compatibility Tools.

0x8007002 –
To resolve this issue, try the OS Deployment test on a client in same VLAN as the Configuration Manager server. Check the network configuration for random client-server connection issues happening on the remote VLAN.

0x8007025D – 0x2000C –
Redownload the ISO/Media and re-attempt the upgrade. Alternatively, re-create installation media the Media Creation Tool.

0x80070490 – 0x20007 –
Verify device drivers on the computer, and analyze log files to determine the problem driver.

0xC1900101 – 0x2000C –
Update drivers on the computer, and select “Download and install updates (recommended)” during the upgrade process. Disconnect devices other than the mouse, keyboard and display.

0xC1900200 – 0x20008 –
See Windows 10 Specifications and verify the computer meets minimum requirements.

0x80070004 – 0x3000D –
Analyze log files to determine the issue.

0x80070005 – 0x4000D –
Refer to error 0x80070004 – 0x3000D.

0x80070004 – 0x50012 –
Refer to error 0x80070004 – 0x3000D.

0xC190020E –
These errors indicate the computer does not have enough free space available to install the upgrade.

0x80070070 – 0x50011 –
These errors indicate the computer does not have enough free space available to install the upgrade.

0x80070070 – 0x50012 –
These errors indicate the computer does not have enough free space available to install the upgrade.

0x80070070 – 0x60000 –
These errors indicate the computer does not have enough free space available to install the upgrade.

 

 

TIPS

The following steps can resolve many Windows upgrade problems:

Remove nonessential external hardware, such as docks and USB devices.

Check all hard drives for errors and attempt repairs. To automatically repair hard drives, open an elevated command prompt, switch to the drive you wish to repair, and type the following command chkdsk /F. You will be required to reboot the computer if the hard drive being repaired is also the system drive.

Attempt to restore and repair system files by typing the following commands DISM.exe /Online /Cleanup-image /Restorehealth , sfc /scannow at an elevated command prompt. It may take several minutes for the command operations to be completed.

Update Windows so that all available recommended updates are installed.

Uninstall non-Microsoft antivirus software.

Uninstall all nonessential software.

Update firmware and drivers.

Ensure that “Download and install updates (recommended)” is accepted at the start of the upgrade process.

Verify at least 16 GB of free space is available to upgrade a 32-bit OS, or 20 GB for a 64-bit OS and 2 GB at least for Windows 10 mobile.

SCCM – Advertisement Statuses

email me

These are codes you will see in the Message ID section in SCCM > Monitoring > Deployment Status — while upgrading/installing Windows 10.

0 0 No Status No messages have been received
10000 2 Rejected Program rejected (offer data integrity)
10001 11 Failed Program rejected (package data integrity)
10002 1 Accepted Program received
10003 11 Failed Failed (bad environment)
10004 11 Failed Program failed
10005 9 Running Program started
10006 11 Failed Program failed
10007 11 Failed Program failed
10008 13 Succeeded Program completed with success
10009 13 Succeeded Program completed with success
10018 2 Rejected Program rejected (wrong platform)
10019 3 Expired Program expired
10020 8 Waiting Program deferred due to slow link
10021 11 Failed Program failed (unexpected restart)
10022 12 Reboot Pending Program completed successfully (reboot pending)
10023 5 Download in Progress Download Started
10024 6 Download Complete Download complete
10025 11 Failed Download failed
10030 11 Failed Download failed – content mismatch
10031 7 Cancelled Download cancelled
10034 7 Cancelled Program cancelled by user
10035 8 Waiting Waiting for content
10036 8 Waiting Waiting for user condition
10037 8 Waiting Waiting for another program
10040 13 Succeeded Program will not rerun
10041 4 Will Not Rerun Program will not rerun
10042 4 Will Not Rerun Program will not rerun
10045 10 Retrying Not enough space in cache
10046 10 Retrying Unable to perform Windows Installer per-user elevation
10050 11 Failed Cache too small
10051 11 Failed Program failed (no content)
10052 2 Rejected Program rejected (invalid policy)
10053 11 Failed Program failed (download failed)
10054 11 Failed Not enough space in cache
10055 10 Retrying Retry (Bad environment)
10056 10 Retrying Program failed (retrying)
10057 11 Failed Program failed (download failed – content mismatch)
10058 11 Failed Program failed (download/location failure)
10060 10 Retrying Program retrying (no content)
10061 10 Retrying Download failed (retrying)
10062 10 Retrying Program retrying (download/location failure)
10070 11 Failed Program failed (run time exceeded)
10071 10 Retrying Program failed (retrying)
10072 10 Retrying Program failed (retrying)
10073 8 Waiting Waiting for a Service Window
10074 11 Failed Program may never run due to Service Window Constraints
10075 12 Reboot Pending Waiting for a Service Window to Reboot Machine
10076 12 Reboot Pending Rebooted Machine Outside of Service Windows
10077 8 Waiting Waiting for Content Availability on a local DP to run the Program from Network
10078 11 Failed Failed to Run. Internet based system timed out waiting for a local network DP
10079 11 Failed System may never Reboot due to Service Window Constraints
10080 11 Failed Failed to Run. The Operating System Deployment Task Sequence cannot run while the client is on the Internet
10800 14 Advanced Client Installed Advanced client successfully installed
10802 14 Advanced Client Installed Advanced client successfully upgraded
10809 14 Advanced Client Installed Advanced client successfully repaired
11010 1 Accepted Device program policy received
11020 1 Accepted Device program content request received
11030 5 Download in Progress Device program download started
11031 9 Running Device program download succeeded
11032 11 Failed Device program download failed
11035 13 Succeeded Device program execution succeeded
11036 11 Failed Device program execution failed
11100 21 Action Started OS installation successfully started an action
11101 11 Failed OS installation action failed
11102 13 Succeeded OS installation completed successfully
11103 11 Failed OS installation failed to request distribution points from management point
11104 11 Failed OS installation failed because there are no distribution points available
11105 11 Failed OS installation failed to connect to the distribution point
11106 15 Validation OS installation successfully started the Validation phase
11107 16 State Capture OS installation successfully started the State Capture phase
11108 17 Preinstall OS installation successfully started the Preinstall phase
11109 18 Install OS installation successfully started the Install phase
11110 19 Postinstall OS installation successfully started the Postinstall phase
11111 20 State Restore OS installation successfully started the State Restore phase
11120 9 Running The task sequence execution engine skipped a disabled group
11121 9 Running The task sequence execution engine failed evaluating the condition for a group
11122 9 Running The task sequence execution engine skipped a group because the condition was evaluated to be false
11123 9 Running The task sequence execution engine evaluated TRUE for the condition of a group
11124 9 Running The task sequence execution engine started a group
11125 9 Running The task sequence execution engine ignored execution failure in a group
11126 9 Running The task sequence execution engine aborted execution for a failure in a group
11127 9 Running The task sequence execution engine successfully completed execution of a group
11128 9 Running The task sequence execution engine skipped a disabled action
11129 9 Running The task sequence execution engine failed evaluating the condition for an action
11130 9 Running The task sequence execution engine skipped an action because the condition was evaluated to be false
11131 9 Running The task sequence execution engine evaluated TRUE for the condition of an action
11132 9 Running The task sequence execution engine failed to start an action
11133 9 Running The task sequence execution engine successfully started an action
11134 9 Running The task sequence execution engine successfully completed an action
11135 9 Running The task sequence execution engine failed executing an action
11136 9 Running The task sequence execution engine received an external shutdown request during execution of an action
11137 9 Running The task sequence execution engine timeout in executing an action
11138 9 Running The task sequence execution engine ignored execution failure of an action
11139 9 Running The task sequence execution engine aborted execution for a failure of an action
11140 9 Running The task sequence execution engine started execution of a task sequence
11141 11 Failed The task sequence execution engine failed execution of a task sequence
11142 9 Running The task sequence execution engine performed a system reboot initiated by an action
11143 13 Succeeded The task sequence execution engine successfully completed a task sequence
11170 11 Failed The task sequence manager could not successfully complete execution of the task sequence
11171 13 Succeeded The task sequence manager successfully completed execution of the task sequence
11200 101 Failed Invalid command line syntax or value
11201 101 Failed Could not retrieve assignment schedule
11202 101 Failed Could not load authorization list
11203 101 Failed Could not locate scan tool cache
11204 101 Failed Attempt to run the scan tool failed
11205 101 Failed Error loading data from WMI.
11206 101 Failed Error writing data to WMI
11207 101 Failed Could not open resource DLL.
11250 103 Retrying Waiting for next advertisement recurrence (change window missed, early start)
11251 103 Retrying Waiting for next advertisement recurrence (change window missed, late start)
11252 104 Postponed Installation was rescheduled by the user
11253 104 Postponed Installation was postponed by the user
11254 104 Postponed Installation was postponed automatically
11255 103 Retrying Installation summary
11256 103 Retrying Waiting for next advertisement recurrence (change window missed, duration expired)
11257 103 Retrying Pre-install reboot was rescheduled by the user
11258 103 Retrying Pre-install reboot was postponed by the user
11259 102 Reboot pending Pre-install reboot was postponed automatically
11260 102 Reboot pending Pre-install reboot was initiated.
11261 102 Reboot pending Installation completed and reboot was rescheduled by the user
11262 102 Reboot pending Installation completed and reboot was postponed by the user
11263 102 Reboot pending Installation completed and reboot was postponed automatically
11264 100 Success Installation completed and a reboot was initiated
11265 100 Success Installation completed and forced reboot was initiated
11266 102 Reboot pending Installation completed and reboot was suppressed for the workstation role
11267 102 Reboot pending Installation completed and reboot was suppressed for the server role
11268 100 Success Installation agent completed and reboot was not needed
11269 103 Retrying Pre-install reboot is needed for installation to continue
11270 102 Reboot pending Reboot of the computer is required.
11300 107 Preliminary Success Installation was successful and a reboot was not indicated
11301 102 Reboot pending Installation was successful and a reboot is needed for the update to take effect
11302 101 Failed Software update failed to install
11303 103 Retrying Installation has timed-out
11304 103 Retrying Installation was cancelled by the user
11306 101 Failed Installation failed because of insufficient disk space
11307 107 Preliminary Success Installation was successful and a reboot was not indicated
11308 102 Reboot pending Installation was successful and a reboot is needed for the update to take effect
11309 107 Preliminary Success Installation was successful and a reboot was not indicated (enforcement date met)
11310 102 Reboot pending Installation was successful and a reboot is needed for the update to take effect (enforcement date met)
11400 101 Failed Cannot access temp folder
11401 101 Failed Unsupported operating system version
11402 101 Failed Cannot access cache folder or no administrative rights available
11403 101 Failed Unsupported version of Internet Explorer
11404 101 Failed Insufficient disk free space (10mb required)
11405 101 Failed Scan results not found
11406 101 Failed Scan failed to update WMI
11408 105 Install Verified Status has changed to installed
11409 106 Uninstalled Status has changed to not installed
11410 101 Failed Unable to read configuration file
11411 101 Failed Unable to meet requirements
11412 101 Failed Unable to execute
11413 101 Failed Unable to expand file
11414 101 Failed Unable to locate scan.ini
11415 100 Success Scan started
11416 101 Failed Failed to start scan
11417 100 Success Scan completed successfully
11418 101 Failed Scan didn’t finish in the expected time
11419 100 Success Scan waiting for contents
11420 101 Failed Scan content download failed
11421 101 Failed Total cache size is insufficient to download the Scan contents
11422 101 Failed Current available cache size is insufficient to download the Scan contents
11423 101 Failed Scan failed
11424 101 Failed Update Source registration failed
11425 101 Failed Scan request with Legacy Scanner is rejected
11426 106 Success Scan succeeded with some extended scan errors
11450 101 Failed SMS Site Code is not specified.
11451 101 Failed Package ID is not specified.
11452 101 Failed SMS Site name is not specified.
11453 101 Failed Package source folder is not specified.
11454 101 Failed Unable to write to package source folder.
11455 101 Failed Unable to read from package source folder.
11456 101 Failed Unable to download catalog
11457 100 Success Catalog download completed successfully
11458 101 Failed Unable to update Distribution Points
11459 101 Failed Unable to update site database from catalog
11460 100 Success Sync operation completed successfully without catalog update
11461 101 Failed The content downloaded can’t be trusted, unable to verify the certificate attached to the content, or no certificate was attached
11462 101 Failed An existing or higher version of a scan tool is already installed at a parent site in the hierarchy
11500 51 Informational Version of device client on attached device is newer. No action taken.
11501 51 Informational No device client action specified. No action taken.
11502 51 Informational Device client installation completed successfully.
11503 51 Informational Device client upgrade completed successfully.
11504 51 Informational Installed device client state verified and settings enforced.
11505 51 Informational Device client uninstallation completed successfully.
11506 51 Informational Device client installation completed successfully and certificate enrollment was not required.
11507 51 Informational Device client upgrade completed successfully and certificate enrollment was not required.
11508 51 Informational Installed Device client state verified, settings enforced and certificate enrollment was not required.
11510 52 Warning Device client installation completed successfully. Certificate installation and/or enrollment failed. Check DmInstaller.log on the Device Client for detailed error information.
11511 52 Warning Device client upgrade completed successfully. Certificate installation and/or enrollment failed. Check DmInstaller.log on the Device Client for detailed error information.
11512 52 Warning Installed device client state verified and settings enforced. Certificate installation and/or enrollment failed. Check DmInstaller.log on the Device Client for detailed error information.
11520 53 Error Device client deployment action failed
11521 53 Error Device client deployment action failed
11522 53 Error Device client deployment action failed
11523 53 Error Device client deployment action failed
11524 53 Error Device client deployment action failed
11525 53 Error Device client deployment action failed
11526 53 Error Device client deployment action failed
11527 53 Error Device client deployment action failed
11528 53 Error Device client deployment action failed
11529 53 Error Device client deployment action failed
11530 53 Error Device client deployment action failed
11540 53 Error Device client deployment action failed
11541 53 Error Device client deployment action failed
11542 53 Error Device client deployment action failed
11550 53 Error Device client installation or upgrade failed. Error during uninstallation of previous client.
11551 53 Error Device client installation or upgrade failed. Invalid client settings file.
11552 53 Error Device client installation or upgrade failed. Error installing client CAB file.
11553 53 Error Device client installation or upgrade failed. Error starting client service.
11554 53 Error Device client installation or upgrade failed. Error updating client settings.
11555 53 Error Device Client Deployment failed with unknown error.
11560 53 Error Device client verification or repair failed. Error during uninstallation of previous client.
11561 53 Error Device client verification or repair failed. Invalid client settings file.
11562 53 Error Device client verification or repair failed. Error installing client CAB file.
11563 53 Error Device client verification or repair failed. Error starting client service.
11564 53 Error Device client verification or repair failed. Error updating client settings.
11565 53 Error Device client verification or repair failed. Error restoring required files.
11566 53 Error Device client privileged certificate installation failed.  Device may have a security policy which prevents the client installer from installing certificates into the privileged and SPC certificate stores.
11567 53 Error Encountered unknown error installing the device client.
11568 53 Error Device client setup failed to launch during install.
11570 53 Error Device client uninstallation failed. Error using unload.exe to uninstall the existing client.
11571 53 Error Device client install/upgrade failed. Error enforcing new client. Device rolled back to old client (if existed before).
11572 53 Error Device client rollback failed during unsuccessful upgrade. Error enforcing old client. Need to freshly install the client.
11573 53 Error Device client failed to perform post cab install actions. Device client installation failed.
11700 101 Failed Scan Tool for this update is not available
11701 101 Failed Scan Tool for this update failed
11702 101 Failed The contents hash for this update provided in policy does not match with the contents downloaded
11703 101 Failed The contents for this update could not be located
11704 101 Failed Contents size for this update exceed free cache size available
11705 101 Failed Contents size for this update exceed total cache size available
11706 101 Failed Failed to download contents for this update
11707 101 Failed This Update cannot be attempted due to invalid commandline
11708 101 Failed This Update application failed
11709 101 Failed This Update did not finish in allocated time
11710 101 Failed Creation of process failed for this update
11711 101 Failed Failed to get installer path for this update
11712 101 Failed Failed to monitor process for this update after service restart
11713 101 Failed SMS internal error occurred for this update
11714 101 Failed Bundle update failed to get content for this update
11715 101 Failed Bundle update failed to install this update
11716 101 Failed Bundle update failed to evaluate the applicability of its leaf updates
11717 101 Failed No current or future maintenance window is available to accomodate this update with max runtime
11750 101 Failed Updates enforcement job failed for this assignment
11751 101 Failed Updates failures occured during enforcement of this assignment
11752 101 Failed Some updates are still non-compliant after enforcemet completion of this assignment
11753 101 Failed Post restart updates compliance checking failed
11754 101 Failed Failed to initiate enforcement of this assignment
11755 101 Failed Failed to initiate updates evaluation for this assignment
11756 101 Failed Updates evaluation job completed with failure for this assignment
11757 101 Failed Invalid policy received for this assignment
11758 101 Failed Failed to initiate updates advance download for assignment
11759 101 Failed Updates advance download job completed with failure for assignment
11760 101 Failed No maintenance window is defined to accommodate at least one update in the deployment
11800 230 Failed Failed to download baseline CI.
11801 230 Failed The contents hash for the baseline CI provided in policy does not match with the contents downloaded.
11802 230 Failed Cannot further process the baseline CI. Managed client does not have the .Net framework version 2.0 installed.
11850 230 Failed Failed to download baseline CI content.
11851 230 Failed The contents hash for the baseline content provided in policy does not match with the contents downloaded.
11852 230 Failed Failed to evaluate baseline content.
11853 230 Failed Failed to report compliance state for baseline content.
11858 230 Failed Baseline CI could not be decompressed.
11859 230 Failed Baseline content could not be decompressed.
11860 230 Failed Internal error – cannot further process baseline content.
11861 230 Failed Internal error – cannot further process baseline CI.
11862 230 Failed Failed to launch discovery process for baseline content.
11863 230 Failed Discovery process crashed for baseline content.
11864 230 Failed Baseline content has model violations.
11865 230 Failed Baseline content encountered one or more errors during discovery.
11866 230 Failed Download of baseline CI timed out.
11867 230 Failed Download of baseline content timed out.
65535 -1 Accepted – No Further Status Program received – no further status

SCCM – Issue Triggers using WMI

email me

Using WMI, this is how you issue  commands to trigger specific SCCM events. Pretty useful if you need to force an inventory refresh…in MDT or remotely. Also see: PowerShell method

 

Command

WMIC /namespace:\\root\ccm path sms_client CALL TriggerSchedule “{00000000-0000-0000-0000-000000000001}” /NOINTERACTIVE


PowerShell Usage

Invoke-WMIMethod -ComputerName $Server -Namespace root\ccm -Class SMS_CLIENT -Name TriggerSchedule “{00000000-0000-0000-0000-000000000001}”

 

Examples


Trigger Hardware Inventory

WMIC /namespace:\\root\ccm path sms_client CALL TriggerSchedule “{00000000-0000-0000-0000-000000000001}” /NOINTERACTIVE


Trigger Software Inventory

WMIC /namespace:\\root\ccm path sms_client CALL TriggerSchedule “{00000000-0000-0000-0000-000000000002}” /NOINTERACTIVE

 

 

Trigger Codes

{00000000-0000-0000-0000-000000000001} Hardware Inventory
{00000000-0000-0000-0000-000000000002} Software Inventory
{00000000-0000-0000-0000-000000000003} Discovery Inventory
{00000000-0000-0000-0000-000000000010} File Collection
{00000000-0000-0000-0000-000000000011} IDMIF Collection
{00000000-0000-0000-0000-000000000012} Client Machine Authentication
{00000000-0000-0000-0000-000000000021} Request Machine Assignments
{00000000-0000-0000-0000-000000000022} Evaluate Machine Policies
{00000000-0000-0000-0000-000000000023} Refresh Default MP Task
{00000000-0000-0000-0000-000000000024} LS (Location Service) Refresh Locations Task
{00000000-0000-0000-0000-000000000025} LS (Location Service) Timeout Refresh Task
{00000000-0000-0000-0000-000000000026} Policy Agent Request Assignment (User)
{00000000-0000-0000-0000-000000000027} Policy Agent Evaluate Assignment (User)
{00000000-0000-0000-0000-000000000031} Software Metering Generating Usage Report
{00000000-0000-0000-0000-000000000032} Source Update Message
{00000000-0000-0000-0000-000000000037} Clearing proxy settings cache
{00000000-0000-0000-0000-000000000040} Machine Policy Agent Cleanup
{00000000-0000-0000-0000-000000000041} User Policy Agent Cleanup
{00000000-0000-0000-0000-000000000042} Policy Agent Validate Machine Policy / Assignment
{00000000-0000-0000-0000-000000000043} Policy Agent Validate User Policy / Assignment
{00000000-0000-0000-0000-000000000051} Retrying/Refreshing certificates in AD on MP
{00000000-0000-0000-0000-000000000061} Peer DP Status reporting
{00000000-0000-0000-0000-000000000062} Peer DP Pending package check schedule
{00000000-0000-0000-0000-000000000063} SUM Updates install schedule
{00000000-0000-0000-0000-000000000071} NAP action
{00000000-0000-0000-0000-000000000101} Hardware Inventory Collection Cycle
{00000000-0000-0000-0000-000000000102} Software Inventory Collection Cycle
{00000000-0000-0000-0000-000000000103} Discovery Data Collection Cycle
{00000000-0000-0000-0000-000000000104} File Collection Cycle
{00000000-0000-0000-0000-000000000105} IDMIF Collection Cycle
{00000000-0000-0000-0000-000000000106} Software Metering Usage Report Cycle
{00000000-0000-0000-0000-000000000107} Windows Installer Source List Update Cycle
{00000000-0000-0000-0000-000000000108} Software Updates Assignments Evaluation Cycle
{00000000-0000-0000-0000-000000000109} Branch Distribution Point Maintenance Task
{00000000-0000-0000-0000-000000000110} DCM policy
{00000000-0000-0000-0000-000000000111} Send Unsent State Message
{00000000-0000-0000-0000-000000000112} State System policy cache cleanout
{00000000-0000-0000-0000-000000000113} Scan by Update Source
{00000000-0000-0000-0000-000000000114} Update Store Policy
{00000000-0000-0000-0000-000000000115} State system policy bulk send high
{00000000-0000-0000-0000-000000000116} State system policy bulk send low
{00000000-0000-0000-0000-000000000120} AMT Status Check Policy
{00000000-0000-0000-0000-000000000121} Application manager policy action
{00000000-0000-0000-0000-000000000122} Application manager user policy action
{00000000-0000-0000-0000-000000000123} Application manager global evaluation action
{00000000-0000-0000-0000-000000000131} Power management start summarizer
{00000000-0000-0000-0000-000000000221} Endpoint deployment reevaluate
{00000000-0000-0000-0000-000000000222} Endpoint AM policy reevaluate
{00000000-0000-0000-0000-000000000223} External event detection

 

Notes

“SendSchedule.exe /L ServerNameHere” to get a list of all triggerable actions for a specific server.

 

Remotely issue the event

$ComputerName = “ComputerNameHere”
$SCCMClient = [wmiclass] “\\$ComputerName\root\ccm:SMS_Client”;
$SCCMClient | Get-Member;

get-wmiobject CCM_Scheduler_ScheduledMessage -namespace root\ccm\policy\machine\actualconfig | select-object ScheduledMessageID, TargetEndPoint | where-object {$_.TargetEndPoint -ne “direct:execmgr”}

try{

$SCCMClient.TriggerSchedule(“{00000000-0000-0000-0000-000000000001}”);

}
catch{
$_.Exception.Message;
}

Windows – Redirect Download Folder

email me

Clear-Host

# DOWNLOADS GUID
$FolderToRedirect = "{374DE290-123F-4565-9164-39C4925E467B}"
# DOWNLOADS VARIABLES

$FolderName = "Downloads"
$LocalPath = "C:\Users\$env:username\$FolderName"
$SharePath = "\\$env:computername\Users\$env:username\$FolderName"
# CREATE DOWNLOADS FOLDER

IF (!(TEST-PATH $LocalPath)) {
New-Item "$LocalPath" -type directory -force
}
# CREATE SHARE OF DOWNLOADS FOLDER

If (!(GET-WMIOBJECT Win32_Share -filter "name='$FolderName'")) {
$Shares=[WMICLASS]"WIN32_Share"
$Shares.Create("$LocalPath","$FolderName",0)
}
# REG KEYS

$ShellFolder = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
$UserShellFolder = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
# REDIRECT TO SHARED PATH

Set-ItemProperty -Path $UserShellFolder -Name "$FolderToRedirect" -Value "$SharePath"
Set-ItemProperty -Path $ShellFolder -Name "$FolderToRedirect" -Value "$SharePath"

# NOTES

# OTHER FOLDER NAMES ARE LOCATED AT
# HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
# HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders

 

Notes

net share Downloads=C:\Users\%username%\Downloads /grant:everyone,FULL

REG DELETE “HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders” /v {374DE290-123F-4565-9164-39C4925E467B} /f

REG DELETE “HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders” /v {374DE290-123F-4565-9164-39C4925E467B} /f

REG ADD “HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders” /v {374DE290-123F-4565-9164-39C4925E467B} /t REG_SZ /d \\%computername%\Users\%username%\Downloads

REG ADD “HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders” /v {374DE290-123F-4565-9164-39C4925E467B} /t REG_SZ /d \\%computername%\Users\%username%\Downloads

————————–

 

Junctions

dir “%userprofile%” /AL

Downloads*{374DE290-123F-4565-9164-39C4925E467B}*%username%*Security*Downloads*\\%computername%\%username%\Downloads

Windows 10 – Start Button Doesn’t Work

email me

From admin prompts

sfc /scannow

Dism /Online /Cleanup-Image /RestoreHealth

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

 

Reinstall

If all else fails, you just might have to reinstall Windows 10.

First, make sure you’ve got an up-to-date backup. If not, copy the contents of your library folders to an external hard drive. You probably won’t need it, but it’s best to be safe.

Press Winkey-L to log out of Windows. Click the the welcome screen to get to the login screen. Click the power button in the lower-right corner, then hold down Shift as you select Restart.

This brings you to the Recovery environment. Select Troubleshoot > Reset this PC > Keep my files and follow the onscreen directions.

When it’s over, you’ll have to reinstall all of the programs that didn’t come with Windows.

 

SCCM – PowerShell – Set up Local Accounts

email me

Clear-Host

$Account = "SCCMAdmin"
$Password = "LetMeIn99$"

# CREATE USER
cmd /c "net user $Account $Password /add /comment:""SCCM Service Account"" "

# SET ACCOUNT TO NEVER EXPIRE
cmd /c "WMIC USERACCOUNT WHERE ""Name='$Account'"" SET PasswordExpires=FALSE"

# ADD ACCOUNT TO ADMIN GROUP
cmd /c "net localgroup ""Administrators"" $Account /add"

# ADD ACCOUNT TO REMOTE GROUP
cmd /c "net localgroup ""ConfigMgr Remote Control Users"" $Account /add"

# ENABLE SECURE ATTENTION SEQUENCE - used by SCCM to allow control-alt-delete
# NOTE - this setting will not trigger the GP in GPEDIT.msc, but will still work
# 0 - None
# 1 - Services
# 2 - Ease of Access applications
# 3 - Services and Ease of Access applications
cmd /c "reg delete ""HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\System"" /v SoftwareSASGeneration /reg:32 /f"
Start-Sleep -s 1
cmd /c "reg add ""HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\System"" /v SoftwareSASGeneration /t REG_DWORD /d 3 /reg:32 /f"

Note: There is a pure PowerShell method to doing all of the above, except it is stupid. Not too sure if Microsoft even uses PowerShell, but many of their CmdLets are an exercise in insanity.

SCCM – PowerShell WMI for the SMS_R_System Class

email me

Return All Computer Names

get-wmiobject -NameSpace “root\sms\site_CODE” -ComputerName “SCCMServerName” -Class SMS_R_System| Select Name

Output:

Computer1

Computer2
Computer3
Computer4
Computer5

 

Return Column Names

Get-WmiObject -NameSpace “root\sms\site_CODE” -ComputerName “SCCMServerName” -Query “SELECT * FROM SMS_R_System WHERE Name = `”SCCMServerName`””

Output:

__GENUS : 2
__CLASS : SMS_R_System
__SUPERCLASS : SMS_Resource
__DYNASTY : SMS_BaseClass
__RELPATH : SMS_R_System.ResourceId=1087777777
__PROPERTY_COUNT : 74
__DERIVATION : {SMS_Resource, SMS_BaseClass}
__SERVER : SCCMServerName
__NAMESPACE : root\sms\site_001
__PATH : \\SCCMServerName\root\sms\site_001:SMS_R_System.ResourceId=1087777777
Active :
ADSiteName : TheSiteName
AgentName : {SMS_WINNT_SERVER_DISCOVERY_AGENT, SMS_NETWORK_DISCOVERY}
AgentSite : {001, 001}
AgentTime : {20170810020232.000000+***, 20170810115753.000000+***}
AlwaysInternet :
AMTFullVersion :
AMTStatus :
Build :
Client :
ClientEdition :
ClientType :
ClientVersion :
CPUType :
CreationDate : 20170527011353.000000+***
Decommissioned : 0
DeviceOwner :
DistinguishedName :
EASDeviceID :
FullDomainName :
HardwareID :
InternetEnabled :
IPAddresses : {10.10.10.10}
IPSubnets : {10.10.10.0}
IPv6Addresses : {}
IPv6Prefixes : {}
IsAOACCapable :
IsAssignedToUser :
IsClientAMT30Compatible :
IsMachineChangesPersisted :
IsPortableOperatingSystem :
IsVirtualMachine : False
IsWriteFilterCapable :
LastLogonTimestamp :
LastLogonUserDomain :
LastLogonUserName :
MACAddresses : {}
ManagementAuthority :
MDMComplianceStatus :
MDMDeviceCategoryID :
Name : SCCMServerName
NetbiosName : SCCMServerName
ObjectGUID :
Obsolete :
OperatingSystemNameandVersion : Microsoft Windows NT Server 10.0
OSBranch :
PreviousSMSUUID :
PrimaryGroupID :
PublisherDeviceID :
ResourceDomainORWorkgroup : DOMAIN
ResourceId : 1087777777
ResourceNames : {SCCMServerName.DOMAIN.com}
ResourceType : 5
SecurityGroupName : {}
SerialNumber :
SID :
SMBIOSGUID :
SMSAssignedSites : {001}
SMSInstalledSites : {}
SMSResidentSites : {001}
SMSUniqueIdentifier :
SMSUUIDChangeDate :
SNMPCommunityName :
SuppressAutoProvision :
SystemContainerName : {}
SystemGroupName : {}
SystemOUName : {}
SystemRoles : {AI Update Service Point, SMS Component Server, SMS Distribution Point, SMS Dmp
Connector…}
Unknown :
UserAccountControl :
VirtualMachineHostName :
VirtualMachineType : 0
WipeStatus :
WTGUniqueKey :
PSComputerName : SCCMServerName

C# – What’s new in C# 7

email me

C# 7 adds a number of new features to the C# language:

  • out variables:
    • You can declare out values inline as arguments to the method where they are used.
  • Tuples
    • You can create lightweight, unnamed types that contain multiple public fields. Compilers and IDE tools understand the semantics of these types.
  • Discards Discards are temporary, write-only variables used in assignments when you don’t care about the value assigned. They are particularly useful when deconstructing tuples and user-defined types, as well as when calling methods with out parameters.
  • Pattern Matching
    • You can create branching logic based on arbitrary types and values of the members of those types.
  • ref locals and returns
    • Method arguments and local variables can be references to other storage.
  • Local Functions
    • You can nest functions inside other functions to limit their scope and visibility.
  • More expression-bodied members
    • The list of members that can be authored using expressions has grown.
  • throw Expressions
    • You can throw exceptions in code constructs that previously were not allowed because throw was a statement.
  • Generalized async return types
    • Methods declared with the async modifier can return other types in addition to Task and Task<T>.
  • Numeric literal syntax improvements
    • New tokens improve readability for numeric constants.

The remainder of this topic discusses each of the features. For each feature, you’ll learn the reasoning behind it. You’ll learn the syntax. You’ll see some sample scenarios where using the new feature will make you more productive as a developer.

out variables

The existing syntax that supports out parameters has been improved in this version.

Previously, you would need to separate the declaration of the out variable and its initialization into two different statements:

C#
int numericResult;
if (int.TryParse(input, out numericResult))
    WriteLine(numericResult);
else
    WriteLine("Could not parse input");

You can now declare out variables in the argument list of a method call, rather than writing a separate declaration statement:

C#
if (int.TryParse(input, out int result))
    WriteLine(result);
else
    WriteLine("Could not parse input");

You may want to specify the type of the out variable for clarity, as shown above. However, the language does support using an implicitly typed local variable:

C#
if (int.TryParse(input, out var answer))
    WriteLine(answer);
else
    WriteLine("Could not parse input");
  • The code is easier to read.
    • You declare the out variable where you use it, not on another line above.
  • No need to assign an initial value.
    • By declaring the out variable where it is used in a method call, you can’t accidentally use it before it is assigned.

The most common use for this feature will be the Try pattern. In this pattern, a method returns a bool indicating success or failure and an out variable that provides the result if the method succeeds.

When using the out variable declaration, the declared variable “leaks” into the outer scope of the if statement. This allows you to use the variable afterwards:

C#
if (!int.TryParse(input, out int result))
{    
    return null;
}

return result;

Tuples

Note

The new tuples features require the ValueTuple types. You must add the NuGet package System.ValueTuple in order to use it on platforms that do not include the types.

This is similar to other language features that rely on types delivered in the framework. Example include async and await relying on the INotifyCompletion interface, and LINQ relying on IEnumerable<T>. However, the delivery mechanism is changing as .NET is becoming more platform independent. The .NET Framework may not always ship on the same cadence as the language compiler. When new language features rely on new types, those types will be available as NuGet packages when the language features ship. As these new types get added to the .NET Standard API and delivered as part of the framework, the NuGet package requirement will be removed.

C# provides a rich syntax for classes and structs that is used to explain your design intent. But sometimes that rich syntax requires extra work with minimal benefit. You may often write methods that need a simple structure containing more than one data element. To support these scenarios tuples were added to C#. Tuples are lightweight data structures that contain multiple fields to represent the data members. The fields are not validated, and you cannot define your own methods

Note

Tuples were available before C# 7, but they were inefficient and had no language support. This meant that tuple elements could only be referenced as Item1, Item2 and so on. C# 7 introduces language support for tuples, which enables semantic names for the fields of a tuple using new, more efficient tuple types.

You can create a tuple by assigning each member to a value:

C#
var letters = ("a", "b");

That assignment creates a tuple whose members are Item1 and Item2, which you can use in the same way as Tuple You can change the syntax to create a tuple that provides semantic names to each of the members of the tuple:

C#
(string Alpha, string Beta) namedLetters = ("a", "b");

The namedLetters tuple contains fields referred to as Alpha and Beta. Those names exist only at compile time and are not preserved for example when inspecting the tuple using reflection at runtime.

In a tuple assignment, you can also specify the names of the fields on the right-hand side of the assignment:

C#
var alphabetStart = (Alpha: "a", Beta: "b");

You can specify names for the fields on both the left and right-hand side of the assignment:

C#
(string First, string Second) firstLetters = (Alpha: "a", Beta: "b");

The line above generates a warning, CS8123, telling you that the names on the right side of the assignment, Alpha and Beta are ignored because they conflict with the names on the left side, First and Second.

The examples above show the basic syntax to declare tuples. Tuples are most useful as return types for private and internal methods. Tuples provide a simple syntax for those methods to return multiple discrete values: You save the work of authoring a class or a struct that defines the type returned. There is no need for creating a new type.

Creating a tuple is more efficient and more productive. It is a simpler, lightweight syntax to define a data structure that carries more than one value. The example method below returns the minimum and maximum values found in a sequence of integers:

C#
private static (int Max, int Min) Range(IEnumerable<int> numbers)
{
    int min = int.MaxValue;
    int max = int.MinValue;
    foreach(var n in numbers)
    {
        min = (n < min) ? n : min;
        max = (n > max) ? n : max;
    }
    return (max, min);
}

Using tuples in this way offers several advantages:

  • You save the work of authoring a class or a struct that defines the type returned.
  • You do not need to create new type.
  • The language enhancements removes the need to call the Create<T1>(T1) methods.

The declaration for the method provides the names for the fields of the tuple that is returned. When you call the method, the return value is a tuple whose fields are Max and Min:

C#
var range = Range(numbers);

There may be times when you want to unpackage the members of a tuple that were returned from a method. You can do that by declaring separate variables for each of the values in the tuple. This is called deconstructing the tuple:

C#
(int max, int min) = Range(numbers);

You can also provide a similar deconstruction for any type in .NET. This is done by writing a Deconstruct method as a member of the class. That Deconstruct method provides a set of out arguments for each of the properties you want to extract. Consider this Point class that provides a deconstructor method that extracts the X and Y coordinates:

C#
public class Point
{
    public Point(double x, double y)
    {
        this.X = x;
        this.Y = y;
    }

    public double X { get; }
    public double Y { get; }

    public void Deconstruct(out double x, out double y)
    {
        x = this.X;
        y = this.Y;
    }
}

You can extract the individual fields by assigning a tuple to a Point:

C#
var p = new Point(3.14, 2.71);
(double X, double Y) = p;

You are not bound by the names defined in the Deconstruct method. You can rename the extract variables as part of the assignment:

C#
(double horizontalDistance, double verticalDistance) = p;

You can learn more in depth about tuples in the tuples topic.

Discards

Often when deconstructing a tuple or calling a method with out parameters, you’re forced to define a variable whose value you don’t care about and don’t intend to use. C# adds support for discards to handle this scenario. A discard is a write-only variable whose name is _ (the underscore character); you can assign all of the values that you intend to discard to the single variable. A discard is like an unassigned variable; apart from the assignment statement, the discard can’t be used in code.

Discards are supported in the following scenarios:

  • When deconstructing tuples or user-defined types.
  • When calling methods with out parameters.
  • In a pattern matching operation with the is and switch statements.
  • As a standalone identifier when you want to explicitly identify the value of an assignment as a discard.

The following example defines a QueryCityDataForYears method that returns a 6-tuple that contains a data for a city for two different years. The method call in the example is concerned only with the two population values returned by the method and so treats the remaining values in the tuple as discards when it deconstructs the tuple.

C#
using System;
using System.Collections.Generic;

public class Example
{
   public static void Main()
   {
       var (_, _, _, pop1, _, pop2) = QueryCityDataForYears("New York City", 1960, 2010);

       Console.WriteLine($"Population change, 1960 to 2010: {pop2 - pop1:N0}");
   }
   
   private static (string, double, int, int, int, int) QueryCityDataForYears(string name, int year1, int year2)
   {
      int population1 = 0, population2 = 0;
      double area = 0;
      
      if (name == "New York City") {
         area = 468.48; 
         if (year1 == 1960) {
            population1 = 7781984;
         }
         if (year2 == 2010) {
            population2 = 8175133;
         }
      return (name, area, year1, population1, year2, population2);
      }

      return ("", 0, 0, 0, 0, 0);
   }
}
// The example displays the following output:
//      Population change, 1960 to 2010: 393,149

For more information, see Discards.

Pattern matching

Pattern matching is a feature that allows you to implement method dispatch on properties other than the type of an object. You’re probably already familiar with method dispatch based on the type of an object. In Object Oriented programming, virtual and override methods provide language syntax to implement method dispatching based on an object’s type. Base and Derived classes provide different implementations. Pattern matching expressions extend this concept so that you can easily implement similar dispatch patterns for types and data elements that are not related through an inheritance hierarchy.

Pattern matching supports is expressions and switch expressions. Each enables inspecting an object and its properties to determine if that object satisfies the sought pattern. You use the when keyword to specify additional rules to the pattern.

is expression

The is pattern expression extends the familiar is operator to query an object beyond its type.

Let’s start with a simple scenario. We’ll add capabilities to this scenario that demonstrate how pattern matching expressions make algorithms that work with unrelated types easy. We’ll start with a method that computes the sum of a number of die rolls:

C#
public static int DiceSum(IEnumerable<int> values)
{
    return values.Sum();
}

You might quickly find that you need to find the sum of die rolls where some of the rolls are made with more than one die. Part of the input sequence may be multiple results instead of a single number:

C#
public static int DiceSum2(IEnumerable<object> values)
{
    var sum = 0;
    foreach(var item in values)
    {
        if (item is int val)
            sum += val;
        else if (item is IEnumerable<object> subList)
            sum += DiceSum2(subList);
    }
    return sum;
}

The is pattern expression works quite well in this scenario. As part of checking the type, you write a variable initialization. This creates a new variable of the validated runtime type.

As you keep extending these scenarios, you may find that you build more if and else if statements. Once that becomes unwieldy, you’ll likely want to switch to switch pattern expressions.

switch statement updates

The match expression has a familiar syntax, based on the switch statement already part of the C# language. Let’s translate the existing code to use a match expression before adding new cases:

C#
public static int DiceSum3(IEnumerable<object> values)
{
    var sum = 0;
    foreach (var item in values)
    {
        switch (item)
        {
            case int val:
                sum += val;
                break;
            case IEnumerable<object> subList:
                sum += DiceSum3(subList);
                break;
        }
    }
    return sum;
}

The match expressions have a slightly different syntax than the is expressions, where you declare the type and variable at the beginning of the case expression.

The match expressions also support constants. This can save time by factoring out simple cases:

C#
public static int DiceSum4(IEnumerable<object> values)
{
    var sum = 0;
    foreach (var item in values)
    {
        switch (item)
        {
            case 0:
                break;
            case int val:
                sum += val;
                break;
            case IEnumerable<object> subList when subList.Any():
                sum += DiceSum4(subList);
                break;
            case IEnumerable<object> subList:
                break;
            case null:
                break;
            default:
                throw new InvalidOperationException("unknown item type");
        }
    }
    return sum;
}

The code above adds cases for 0 as a special case of int, and null as a special case when there is no input. This demonstrates one important new feature in switch pattern expressions: the order of the case expressions now matters. The 0 case must appear before the general int case. Otherwise, the first pattern to match would be the int case, even when the value is 0. If you accidentally order match expressions such that a later case has already been handled, the compiler will flag that and generate an error.

This same behavior enables the special case for an empty input sequence. You can see that the case for an IEnumerable item that has elements must appear before the general IEnumerable case.

This version has also added a default case. The default case is always evaluated last, regardless of the order it appears in the source. For that reason, convention is to put the default case last.

Finally, let’s add one last case for a new style of die. Some games use percentile dice to represent larger ranges of numbers.

Note

Two 10-sided percentile dice can represent every number from 0 through 99. One die has sides labelled 00, 10, 20, … 90. The other die has sides labeled 0, 1, 2, … 9. Add the two die values together and you can get every number from 0 through 99.

To add this kind of die to your collection, first define a type to represent the percentile die:

C#
public struct PercentileDie
{
    public int Value { get; }
    public int Multiplier { get; }

    public PercentileDie(int multiplier, int value)
    {
        this.Value = value;
        this.Multiplier = multiplier;
    }
}

Then, add a case match expression for the new type:

C#
public static int DiceSum5(IEnumerable<object> values)
{
    var sum = 0;
    foreach (var item in values)
    {
        switch (item)
        {
            case 0:
                break;
            case int val:
                sum += val;
                break;
            case PercentileDie die:
                sum += die.Multiplier * die.Value;
                break;
            case IEnumerable<object> subList when subList.Any():
                sum += DiceSum5(subList);
                break;
            case IEnumerable<object> subList:
                break;
            case null:
                break;
            default:
                throw new InvalidOperationException("unknown item type");
        }
    }
    return sum;
}

The new syntax for pattern matching expressions makes it easier to create dispatch algorithms based on an object’s type, or other properties, using a clear and concise syntax. Pattern matching expressions enable these constructs on data types that are unrelated by inheritance.

You can learn more about pattern matching in the topic dedicated to pattern matching in C#.

Ref locals and returns

This feature enables algorithms that use and return references to variables defined elsewhere. One example is working with large matrices, and finding a single location with certain characteristics. One method would return the two indices for a single location in the matrix:

C#
public static (int i, int j) Find(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return (i, j);
    return (-1, -1); // Not found
}

There are many issues with this code. First of all, it’s a public method that’s returning a tuple. The language supports this, but user defined types (either classes or structs) are preferred for public APIs.

Second, this method is returning the indices to the item in the matrix. That leads callers to write code that uses those indices to dereference the matrix and modify a single element:

C#
var indices = MatrixSearch.Find(matrix, (val) => val == 42);
Console.WriteLine(indices);
matrix[indices.i, indices.j] = 24;

You’d rather write a method that returns a reference to the element of the matrix that you want to change. You could only accomplish this by using unsafe code and returning a pointer to an int in previous versions.

Let’s walk through a series of changes to demonstrate the ref local feature and show how to create a method that returns a reference to internal storage. Along the way, you’ll learn the rules of the ref return and ref local feature that protects you from accidentally misusing it.

Start by modifying the Find method declaration so that it returns a ref int instead of a tuple. Then, modify the return statement so it returns the value stored in the matrix instead of the two indices:

C#
// Note that this won't compile. 
// Method declaration indicates ref return,
// but return statement specifies a value return.
public static ref int Find2(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return matrix[i, j];
    throw new InvalidOperationException("Not found");
}

When you declare that a method returns a ref variable, you must also add the ref keyword to each return statement. That indicates return by reference, and helps developers reading the code later remember that the method returns by reference:

C#
public static ref int Find3(int[,] matrix, Func<int, bool> predicate)
{
    for (int i = 0; i < matrix.GetLength(0); i++)
        for (int j = 0; j < matrix.GetLength(1); j++)
            if (predicate(matrix[i, j]))
                return ref matrix[i, j];
    throw new InvalidOperationException("Not found");
}

Now that the method returns a reference to the integer value in the matrix, you need to modify where it’s called. The var declaration means that valItem is now an int rather than a tuple:

C#
var valItem = MatrixSearch.Find3(matrix, (val) => val == 42);
Console.WriteLine(valItem);
valItem = 24;
Console.WriteLine(matrix[4, 2]);

The second WriteLine statement in the example above prints out the value 42, not 24. The variable valItem is an int, not a ref int. The var keyword enables the compiler to specify the type, but will not implicitly add the ref modifier. Instead, the value referred to by the ref return is copied to the variable on the left-hand side of the assignment. The variable is not a ref local.

In order to get the result you want, you need to add the ref modifier to the local variable declaration to make the variable a reference when the return value is a reference:

C#
ref var item = ref MatrixSearch.Find3(matrix, (val) => val == 42);
Console.WriteLine(item);
item = 24;
Console.WriteLine(matrix[4, 2]);

Now, the second WriteLine statement in the example above will print out the value 24, indicating that the storage in the matrix has been modified. The local variable has been declared with the ref modifier, and it will take a ref return. You must initialize a ref variable when it is declared, you cannot split the declaration and the initialization.

The C# language has three other rules that protect you from misusing the ref locals and returns:

  • You cannot assign a standard method return value to a ref local variable.
    • That disallows statements like ref int i = sequence.Count();
  • You cannot return a ref to a variable whose lifetime does not extend beyond the execution of the method.
    • That means you cannot return a reference to a local variable or a variable with a similar scope.
  • ref locals and returns can’t be used with async methods.
    • The compiler can’t know if the referenced variable has been set to its final value when the async method returns.

The addition of ref locals and ref returns enable algorithms that are more efficient by avoiding copying values, or performing dereferencing operations multiple times.

Local functions

Many designs for classes include methods that are called from only one location. These additional private methods keep each method small and focused. However, they can make it harder to understand a class when reading it the first time. These methods must be understood outside of the context of the single calling location.

For those designs, local functions enable you to declare methods inside the context of another method. This makes it easier for readers of the class to see that the local method is only called from the context in which is it declared.

There are two very common use cases for local functions: public iterator methods and public async methods. Both types of methods generate code that reports errors later than programmers might expect. In the case of iterator methods, any exceptions are observed only when calling code that enumerates the returned sequence. In the case of async methods, any exceptions are only observed when the returned Task is awaited.

Let’s start with an iterator method:

C#
public static IEnumerable<char> AlphabetSubset(char start, char end)
{
    if (start < 'a' || start > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if (end < 'a' || end > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");
    for (var c = start; c < end; c++)
        yield return c;
}

Examine the code below that calls the iterator method incorrectly:

C#
var resultSet = Iterator.AlphabetSubset('f', 'a');
Console.WriteLine("iterator created");
foreach (var thing in resultSet)
    Console.Write($"{thing}, ");

The exception is thrown when resultSet is iterated, not when resultSet is created. In this contained example, most developers could quickly diagnose the problem. However, in larger codebases, the code that creates an iterator often isn’t as close to the code that enumerates the result. You can refactor the code so that the public method validates all arguments, and a private method generates the enumeration:

C#
public static IEnumerable<char> AlphabetSubset2(char start, char end)
{
    if (start < 'a' || start > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if (end < 'a' || end > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");
    return alphabetSubsetImplementation(start, end);
}

private static IEnumerable<char> alphabetSubsetImplementation(char start, char end)
{ 
    for (var c = start; c < end; c++)
        yield return c;
}

This refactored version will throw exceptions immediately because the public method is not an iterator method; only the private method uses the yield return syntax. However, there are potential problems with this refactoring. The private method should only be called from the public interface method, because otherwise all argument validation is skipped. Readers of the class must discover this fact by reading the entire class and searching for any other references to the alphabetSubsetImplementation method.

You can make that design intent more clear by declaring the alphabetSubsetImplementation as a local function inside the public API method:

C#
public static IEnumerable<char> AlphabetSubset3(char start, char end)
{
    if (start < 'a' || start > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(start), message: "start must be a letter");
    if (end < 'a' || end > 'z')
        throw new ArgumentOutOfRangeException(paramName: nameof(end), message: "end must be a letter");

    if (end <= start)
        throw new ArgumentException($"{nameof(end)} must be greater than {nameof(start)}");

    return alphabetSubsetImplementation();

    IEnumerable<char> alphabetSubsetImplementation()
    {
        for (var c = start; c < end; c++)
            yield return c;
    }
}

The version above makes it clear that the local method is referenced only in the context of the outer method. The rules for local functions also ensure that a developer can’t accidentally call the local function from another location in the class and bypass the argument validation.

The same technique can be employed with async methods to ensure that exceptions arising from argument validation are thrown before the asynchronous work begins:

C#
public Task<string> PerformLongRunningWork(string address, int index, string name)
{
    if (string.IsNullOrWhiteSpace(address))
        throw new ArgumentException(message: "An address is required", paramName: nameof(address));
    if (index < 0)
        throw new ArgumentOutOfRangeException(paramName: nameof(index), message: "The index must be non-negative");
    if (string.IsNullOrWhiteSpace(name))
        throw new ArgumentException(message: "You must supply a name", paramName: nameof(name));

    return longRunningWorkImplementation();

    async Task<string> longRunningWorkImplementation()
    {
        var interimResult = await FirstWork(address);
        var secondResult = await SecondStep(index, name);
        return $"The results are {interimResult} and {secondResult}. Enjoy.";
    }
}
Note

Some of the designs that are supported by local functions could also be accomplished using lambda expressions. Those interested can read more about the differences

More expression-bodied members

C# 6 introduced expression-bodied members for member functions, and read-only properties. C# 7 expands the allowed members that can be implemented as expressions. In C# 7, you can implement constructors, finalizers, and get and set accessors on properties and indexers. The following code shows examples of each:

C#
// Expression-bodied constructor
public ExpressionMembersExample(string label) => this.Label = label;

// Expression-bodied finalizer
~ExpressionMembersExample() => Console.Error.WriteLine("Finalized!");

private string label;

// Expression-bodied get / set accessors.
public string Label
{
    get => label;
    set => this.label = value ?? "Default label";
}
Note

This example does not need a finalizer, but it is shown to demonstrate the syntax. You should not implement a finalizer in your class unless it is necessary to release unmanaged resources. You should also consider using the SafeHandle class instead of managing unmanaged resources directly.

These new locations for expression-bodied members represent an important milestone for the C# language: These features were implemented by community members working on the open-source Roslyn project.

Throw expressions

In C#, throw has always been a statement. Because throw is a statement, not an expression, there were C# constructs where you could not use it. These included conditional expressions, null coalescing expressions, and some lambda expressions. The addition of expression-bodied members adds more locations where throw expressions would be useful. So that you can write any of these constructs, C# 7 introduces throw expressions.

The syntax is the same as you’ve always used for throw statements. The only difference is that now you can place them in new locations, such as in a conditional expression:

C#
public string Name
{
    get => name;
    set => name = value ?? 
        throw new ArgumentNullException(paramName: nameof(value), message: "New name must not be null");
}

This features enables using throw expressions in initialization expressions:

C#
private ConfigResource loadedConfig = LoadConfigResourceOrDefault() ?? 
    throw new InvalidOperationException("Could not load config");

Previously, those initializations would need to be in a constructor, with the throw statements in the body of the constructor:

C#
public ApplicationOptions()
{
    loadedConfig = LoadConfigResourceOrDefault();
    if (loadedConfig == null)
        throw new InvalidOperationException("Could not load config");

}
Note

Both of the preceding constructs will cause exceptions to be thrown during the construction of an object. Those are often difficult to recover from. For that reason, designs that throw exceptions during construction are discouraged.

Generalized async return types

Returning a Task object from async methods can introduce performance bottlenecks in certain paths. Task is a reference type, so using it means allocating an object. In cases where a method declared with the async modifier returns a cached result, or completes synchronously, the extra allocations can become a significant time cost in performance critical sections of code. It can become very costly if those allocations occur in tight loops.

The new language feature means that async methods may return other types in addition to Task, Task<T> and void. The returned type must still satisfy the async pattern, meaning a GetAwaiter method must be accessible. As one concrete example, the ValueTask type has been added to the .NET framework to make use of this new language feature:

C#
public async ValueTask<int> Func()
{
    await Task.Delay(100);
    return 5;
}
Note

You need to add the NuGet package System.Threading.Tasks.Extensions in order to use the ValueTask<TResult> type.

A simple optimization would be to use ValueTask in places where Task would be used before. However, if you want to perform extra optimizations by hand, you can cache results from async work and reuse the result in subsequent calls. The ValueTask struct has a constructor with a Task parameter so that you can construct a ValueTask from the return value of any existing async method:

C#
public ValueTask<int> CachedFunc()
{
    return (cache) ? new ValueTask<int>(cacheResult) : new ValueTask<int>(LoadCache());
}
private bool cache = false;
private int cacheResult;
private async Task<int> LoadCache()
{
    // simulate async work:
    await Task.Delay(100);
    cacheResult = 100;
    cache = true;
    return cacheResult;
}

As with all performance recommendations, you should benchmark both versions before making large scale changes to your code.

Numeric literal syntax improvements

Misreading numeric constants can make it harder to understand code when reading it for the first time. This often occurs when those numbers are used as bit masks or other symbolic rather than numeric values. C# 7 includes two new features to make it easier to write numbers in the most readable fashion for the intended use: binary literals, and digit separators.

For those times when you are creating bit masks, or whenever a binary representation of a number makes the most readable code, write that number in binary:

C#
public const int One =  0b0001;
public const int Two =  0b0010;
public const int Four = 0b0100;
public const int Eight = 0b1000;

The 0b at the beginning of the constant indicates that the number is written as a binary number.

Binary numbers can get very long, so it’s often easier to see the bit patterns by introducing the _ as a digit separator:

C#
public const int Sixteen =   0b0001_0000;
public const int ThirtyTwo = 0b0010_0000;
public const int SixtyFour = 0b0100_0000;
public const int OneHundredTwentyEight = 0b1000_0000;

The digit separator can appear anywhere in the constant. For base 10 numbers, it would be common to use it as a thousands separator:

C#
public const long BillionsAndBillions = 100_000_000_000;

The digit separator can be used with decimal, float and double types as well:

C#
public const double AvogadroConstant = 6.022_140_857_747_474e23;
public const decimal GoldenRatio = 1.618_033_988_749_894_848_204_586_834_365_638_117_720_309_179M;

Taken together, you can declare numeric constants with much more readability.

SQL – Cleaning Up Records in Custom Table

email me

This is some SQL code I’m using to clean up some records…it removes unwanted data from a specified table.

USE [CM_001]
GO

UPDATE dbo.Custom_Custom_DATA
SET Bitlocker_D_Drive00 = ''
WHERE Bitlocker_D_Drive00 = 'The parameter is incorrect.'
GO

UPDATE dbo.Custom_Custom_DATA
SET Bitlocker_C_Drive00 = ''
WHERE Bitlocker_C_Drive00 = 'ERROR: No key protectors found.'
GO

UPDATE dbo.Custom_Custom_DATA
SET Bitlocker_C_Drive00 = ''
WHERE Bitlocker_C_Drive00 = 'A system shutdown is in progress.'
GO

UPDATE dbo.Custom_Custom_DATA
SET Bitlocker_D_Drive00 = ''
WHERE Bitlocker_D_Drive00 = 'A system shutdown is in progress.'
GO
UPDATE dbo.Custom_Custom_DATA
SET Bitlocker_C_Drive00 = ''
WHERE Bitlocker_C_Drive00 = 'ERROR: No key protectors found.'
GO

UPDATE dbo.Custom_Custom_DATA
SET Bitlocker_D_Drive00 = ''
WHERE Bitlocker_D_Drive00 = 'ERROR: No key protectors found.'
GO
UPDATE dbo.Custom_Custom_DATA
SET Bitlocker_C_Drive00 = ''
WHERE Bitlocker_C_Drive00 = 'ECHO is on.'
GO

UPDATE dbo.Custom_Custom_DATA
SET Bitlocker_D_Drive00 = ''
WHERE Bitlocker_D_Drive00 = 'ECHO is on.'
GO

SCCM – VBScript – Return Data from SCCM DB No DSN

email me

Still working on this…

I’m going to be creating a small app to manage things like Bitlocker and Remote Support. The first step is to connect and use existing data from the SCCM database.

So far, it does connect and return specific elements from the database. Next, is to create a simple interface.

Note, I’m using the below to return Bitlocker Passwords…ones I stored in the SCCM DB using MOFs.

on error resume next 

Set Connection = CreateObject("ADODB.Connection")
Set Recordset = CreateObject("ADODB.Recordset")
Set filsSysObj = CreateObject("Scripting.FileSystemObject")

Connection.ConnectionString = "Provider=SQLOLEDB;Data Source=YourServer\TheInstanceIfYouHaveOne;Initial Catalog=CM_SiteCodeHere;Integrated Security=SSPI;"
Connection.open

'the sql command...for a custom field created from MOFs
sqlQuery = "SELECT * FROM dbo.Custom_Custom_DATA"

set data = Connection.execute(sqlQuery)

'output of my data
Set output = filsSysObj.OpenTextFile("output.csv", 8, True)

'cycle through the records, outputting specific elements 
do until data.EOF

	MachineID = data.Fields(0).Value 
	CDrive = data.Fields(6).Value
	DDrive = data.Fields(7).Value
	Output.Write MachineID & "," & CDrive & "," & DDrive
	Output.Write vbNewLine

	data.MoveNext
loop

'clean up
output.Close
Connection.Close