sobota, 24 listopada 2018

Life Hacks - Patching a computer without Software Center GUI


    Sometimes you might find yourself in a rare situation when you have an urgent need to immediately patch the computer with an SCCM agent on it, but Software Center refuses to cooperate - it throws errors and does nt open despite several troubleshooting attempts including re-installation of the agent. In this case the following commands might come in handy:

Usage:

    The following cmd command will help you to "see" the actionable patches list as displayed in the Software Center. The exemplary output of the comment is below:

ArticleID=4055532
EvaluationState=6
Name=2018-01 Security and Quality Rollup for .NET Framework 3.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1 on Windows 7 and Server 2008 R2 for x64 (KB4055532)

ArticleID=890830
EvaluationState=6
Name=Windows Malicious Software Removal Tool x64 - February 2018 (KB890830)

ArticleID=4076492
EvaluationState=8
Name=2018-02 Security and Quality Rollup for .NET Framework 3.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1 on Windows 7 and Server 2008 R2 for x64 (KB4076492)

ArticleID=4055269
EvaluationState=6
Name=2018-01 Security Only Update for .NET Framework 3.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1 on Windows 7 and Server 2008 R2 for x64 (KB4055269)


    Below you can find a reference for available Evalutaion state (source: CCM_SoftwareUpdate Client WMI Class)

Value    State

0    ciJobStateNone
1    ciJobStateAvailable
2    ciJobStateSubmitted
3    ciJobStateDetecting
4    ciJobStatePreDownload
5    ciJobStateDownloading
6    ciJobStateWaitInstall
7    ciJobStateInstalling
8    ciJobStatePendingSoftReboot
9    ciJobStatePendingHardReboot
10    ciJobStateWaitReboot
11    ciJobStateVerifying
12    ciJobStateInstallComplete
13    ciJobStateError
14    ciJobStateWaitServiceWindow
15    ciJobStateWaitUserLogon
16    ciJobStateWaitUserLogoff
17    ciJobStateWaitJobUserLogon
18    ciJobStateWaitUserReconnect
19    ciJobStatePendingUserLogoff
20    ciJobStatePendingUpdate
21    ciJobStateWaitingRetry
22    ciJobStateWaitPresModeOff
23    ciJobStateWaitForOrchestration

Code:

wmic /namespace:\\root\ccm\ClientSDK path CCM_SoftwareUpdate WHERE ComplianceState='0'  GET Name,ArticleId,EvaluationState /format:list

Usage:

    The following cmdlets will force the installation of all actionable updates

Code:

$MissingUpdates = Get-WmiObject -Class CCM_SoftwareUpdate -Filter ComplianceState=0 -Namespace root\CCM\ClientSDK
$MissingUpdatesReformatted = @($MissingUpdates | ForEach-Object {IF($_.ComplianceState -eq 0){[WMI]$_.__PATH}})
$InstallReturn = Invoke-WmiMethod -Class CCM_SoftwareUpdatesManager -Name InstallUpdates -ArgumentList (,$MissingUpdatesReformatted) -Namespace root\ccm\ClientSDK

piątek, 7 września 2018

Troubleshooting - Disappering configuration.mof File

Symptoms:

   Recently we noticed an unexpected behavior of Hardware Inventory settings applied in the configuration.mof file on one of our SCCM instances. None of the WMI classes introduced into the file were collected and upon re-checking the file it turned out, that any newly added section were being removed and the file was reverted to it's original form. Interestingly enough, the section added did not contain any errors, as this was happening even in case of adding additional spaces or new lines to the file - they would disappear as well.

Resolution:

    My first suspicion was to verify the extension added by the custom HP inventory module solution, which was only applied on this particular instance and added the following section at the end of the configuration.mof file:



Extension added to configuration.mof file by a custom HP plugin

    Removing this section however didn't take an effect either - the file was restored and the section re-appeared. An action was reflected in the dataldr.log file with the following entries:

MofCompiler failed:
parsing error
Failed to confert MOF class/poperties to policy; a retry will be attemted in 30 seconds...


Errors in the dataldr.log file

    Despite no apparent syntax problems the file refused to get parsed. Even voiding each section one by one didn't fix the problem - an empty file would get removed and restored from backup too. What helped to pinpoint the problem was running file comparison tool FC.exe - against another configuration.mof file from the properly working environment. This revealed the following phenomenon:



Errors in the dataldr.log file

    Apparently the beginning of the file was taken by some special character invisible either notepad or any other editing tool that was available. The problem was fixed by replacing the file with a properly working one and transplanting custom sections from the old faulty one. Looking at the history of the changes it seems that the latest accepted change to the file was accepted after adding the custom HP SCCM plugin

wtorek, 10 lipca 2018

Troubleshooting - Where to Look for SCCM Console's Default Connection Settings

Symptoms:

   Imagine SCCM Console is pushed as an SCCM application and you make a typo in the  properties providing a value of a DefaultSiteServerName parameter (a thing that happened to us recently). Normally it's not a big deal - a single user can correct this by introducing a proper server name on the first screen. Now imagine that apart from other computers the console was installed as well on the RemoteApp server. Every single user starting an application will face the same situation which can result in a significant amount of complaints

Resolution:

    The connection settings for each individual user are stored in the below registry key - HKU\{User_GUID}\Software\Microsoft\ConfigMgr10\AdminUI\MRU\1:



Location of individual SCCM Console connection settings in the registry

    This key is modified automatically once the user introduces a new value at the console startup. However every new user starting a console from the before-mentioned RemoteApp server will initially face the same. We also discovered another interesting phenomenon - upgrading a console on the server resets the above-shown keys to the general value set up during the first installation of the console. So - where is the main value stored? It turned out it is also written in the registry and can be found in the below key - HKLM\SOFTWARE\Microsoft\SMS\Identification:


Location of the main SCCM Console connection settings in the registry

    Changing a value of this key fixes a problem for all the future users. If you want to fix it for all the users already facing a problem, you have to modify their respective keys in the hive mentioned on the first screen-shot.

czwartek, 10 maja 2018

Update - Script Installing Java and Removing any Obsolete Versions v2

    Following up the recent post about removing confidential data from the log files,
that can be found over here:


    It turned out after more in-depth analysis of several scenarios where Java was deployed on the servers rather than workstations, that WMIC CALL UNINSTALL command might sometimes enforce a system restart (a thing that we have never observed on workstations with a first version of the script) and it turns out, that there is no built-in way to avoid this with WMIC. Due to this in the effort to exclude this possibility I wrote a second version of the script, which is based on msiexec /X command, some REG QUERY and -REPLACE manipulations which are extracting GUIDs from the registry and forming msiexec uninstall strings. By doing this we can explicitly add the /norestart parameter which does what we need.

Usage:

    Similarly to the previous version place the script file in the same folder as the Java binaries. Script in the below version is installing Java 8.0.121 and removing any Java version installed on the computer.
    When the SCCM Application is ready, be sure to set up properly detection methods depending on the Java versions that you expect to see on the computer after the installation process completes. I recommend using registry keys for this purpose as in the example below:
Detection method set for Java 8 U 121

Additional Notes:
    In contrary to the first version of the script here there unfortunately is no way to choose which versions of Java we would like to keep on the computer, like with the NOT Version LIKE '8.0.121'" module in the previous script. Therefore filtering has to be performed on the collection rules level. When creating collections for staged deployment include only computers containing Java version you would like to uninstall or which don't contain any Java if you want to push the software to them.
    After setting this up properly I still recommend to divide your environment in several parts, increasing in size and to deploy the script to those collections one by one.

Code:

setLocal EnableDelayedExpansion

REM Stop IE
if EXIST "%WINDIR%\system32\taskkill.exe" (
   taskkill /F /IM iexplore.exe 2> NUL
)

REG QUERY HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /s /f "Java*Update" | findstr "HKEY_LOCAL_MACHINE" >> tmpFile.bat
REG QUERY HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall /s /f "Java*Update" | findstr "HKEY_LOCAL_MACHINE" >> tmpFile.bat

powershell -Command "(gc tmpFile.bat) -replace 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\', 'msiexec /X ' | Out-File -Encoding "Default" tmpFile.bat"
powershell -Command "(gc tmpFile.bat) -replace 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\', 'msiexec /X ' | Out-File -Encoding "Default" tmpFile.bat"
powershell -Command "(gc tmpFile.bat) -replace '\S+$', '$& /quiet /norestart' | Out-File -Encoding "Default" tmpFile.bat"

.\tmpFile.bat
"%~dp0jre-8u121-windows-x64.exe" /s "ADDLOCAL=ALL IEXPLORER=1 MOZILLA=0 JAVAUPDATE=0 REBOOT=Disable"

DEL .\tmpFile.bat

piątek, 20 kwietnia 2018

Script Installing Java and Removing any Obsolete Versions

    Managing centrally Java life-cycle with SCCM might be a little challenging due to the fact, that multiple versions of Java might coexist on one computer. If you add to this, that only some of those versions might be approved to be present in the network (which implies that you might not be allowed to use Java Auto Updater) and that the installer doesn't automatically uninstall old Java version during the installation you find yourself in quite a complex situation. That's when the script below might come in handy. It was written in order to remove all non-approved Java versions, Java Auto Downloader and install the latest approved version of Java

Usage:
    Place the script file in the same folder as the Java binaries. Script in the below version is installing Java 8.0.121 and removing any different version, together with Java Auto Downloader. The NOT Name LIKE '%%DEV%%' exclusion ensures, that Java Development Environment, if exists on the computer, will remain untouched.
    You can add more NOT Version LIKE 'xxx' modules to the wmic command if you have some applications that depend strictly on a particular Java version and you know that it should not be uninstalled.
    When the SCCM Application is ready, be sure to set up properly detection methods depending on the Java versions that you expect to see on the computer after the installation process completes. I recommend using registry keys for this purpose as in the example below:
Detection method set for Java 8 U 121

Additional Notes:
    As in all the scripted deployments you should be very careful. I recommend to verify first which products matching 'Java%%' wildcard do you have in your environment with use Hardware Inventory and either SCCM Reporting or SQL query. 
    When you are sure what you're doing, you can always test several cases on the test computer by calling this part of command only:

wmic product WHERE "Name LIKE 'Java%Update%' AND NOT Name LIKE '%Dev%' AND NOT Version LIKE '8.0.121'"

    By doing this you will verify which programs would be uninstalled when executing your SCCM deployment.
    After checking this I still recommend to go for a staged deployment. Divide your environment in several parts, increasing in size and deploy the script to those collections one by one.

Code:

REM Stop IE

if EXIST "%WINDIR%\system32\taskkill.exe" (
   taskkill /F /IM iexplore.exe 2> NUL
)

wmic product WHERE "Name LIKE 'Java%%Update%%' AND NOT Name LIKE '%%Dev%%' AND NOT Version LIKE '8.0.121'" call uninstall /nointeractive

REM "%~dp0jre-8u121-windows-x64.exe" /s "ADDLOCAL=ALL IEXPLORER=1 MOZILLA=0 JAVAUPDATE=0 REBOOT=Disable"

poniedziałek, 5 marca 2018

How to check which binaries can be removed from SCCM server

    Recently I received an interesting question - can particular folders from the SCCM source share be removed or are they still in use by any application? It can be actually verified with a below SQL query, which helps to identify all folders set as a source for any application or package and matching a certain wildcard chosen by an administrator.


Exemplary output of the folder presence SQL query

Usage:
    Replace the _ServerFQDN_ string with the name of the source server, XXX$ with a name of the share and YYY with a regular expression matching a path to the folders you want to verify. 
    Obviously the query should be run via SQL Management Studio or any other similar tool letting you execute T-SQL queries.

Code:
SELECT Name,PkgSourcePath,ContentSource FROM v_Content
JOIN v_Package ON v_Package.PackageID = v_Content.PkgID
WHERE ContentSource LIKE '\\_ServerFQDN_\XXX$\YYY\%'
OR PkgSourcePath LIKE '\\_ServerFQDN_\XXX$\YYY\%'

poniedziałek, 19 lutego 2018

Checking the Full Folder Path of Collection Objects in SCCM

    Following up the recent post about identifying full folder path in SCCM for certain drivers, that can be found over here:

    I decided to post another, modified SQL query which hopefully will help you in this situation:

 Delete Collection Error - References to Other Collections Block the Delete Collection Action

    We know, that the references to the collection we want to remove in other collections are blocking the possibility to remove our collection. A task to find those collections might not be trivial if you don't know where in SCCM folder structure do they reside. Query below will recursively find the full folder path to those collections based on the regular expressions.

Usage:
    Replace the _CollectionRegexp_ string with the regular expression matching your needs depending on the collections you are looking for.
    Obviously the query should be run via SQL Management Studio or any other similar tool letting you execute T-SQL queries.

Code:
SELECT ROW_NUMBER() OVER (ORDER BY v_Collection.Name,vSMS_Folders.ContainerNodeID) AS [Row], v_Collection.Name, vSMS_Folders.ContainerNodeID,v_Collection.Name AS Folder  INTO #Temp
FROM v_Collection
JOIN vFolderMembers on v_Collection.CollectionID = vFolderMembers.InstanceKey
JOIN vSMS_Folders ON vFolderMembers.ContainerNodeID = vSMS_Folders.ContainerNodeID
WHERE v_Collection.Name LIKE '_CollectionRegexp_'
AND vFolderMembers.ObjectTypeName = 'SMS_Collection_Device'
ORDER BY v_Collection.Name

DECLARE @It INT=1

WHILE (@It <= (SELECT COUNT(*) FROM #Temp))
BEGIN
      DECLARE @ContainerID INT=(SELECT ContainerNodeID FROM #Temp WHERE Row=@It)
      DECLARE @ContainerIDBeg INT=(SELECT ContainerNodeID FROM #Temp WHERE Row=@It)
      DECLARE @ContainerFullName VARCHAR(MAX)
      DECLARE @ContainerName VARCHAR(MAX)
      WHILE (SELECT ParentContainerNodeID FROM vSMS_Folders WHERE ContainerNodeID=@ContainerID) != 0
      BEGIN
            SET @ContainerName = (SELECT Name FROM vSMS_Folders WHERE ContainerNodeID=@ContainerID)
            IF (@ContainerID=(SELECT TOP 1 ContainerNodeID FROM #Temp))
                  SET @ContainerFullName = @ContainerName
            ELSE
                  SET @ContainerFullName = @ContainerName + '\' + @ContainerFullName
            SET @ContainerID = (SELECT ParentContainerNodeID FROM vSMS_Folders WHERE ContainerNodeID=@ContainerID)
      END
SET @ContainerFullName = (SELECT Name FROM vSMS_Folders WHERE ContainerNodeID=@ContainerID) + '\' + @ContainerFullName
UPDATE #Temp
SET Folder = @ContainerFullName
WHERE Row = @It
SET @It += 1
SET @ContainerFullName = ''
END

SELECT Name,Folder FROM #Temp
DROP TABLE #Temp