SCCM – VBScript – Return Records from Database using DSN

email me

This is how you would return specific records from a SQL Database (I’m using a SCCM DB). You could use this to return computer inventory data, SCCM administrative info, or reporting information….or you could wrap the returned data into a function and create a support application, like remotely connecting to a computer using CmRcViewer.exe, located in: D:\Program Files\Microsoft Configuration Manager\AdminConsole\bin\i386.

This could be easily ported to PowerShell or C#.

Note: The user account should eventually become a service account…and all resource files should be compiled.

Screenshot


For example, to return Usernames in the User_DISC table…

Script

Dim Connection, Recordset, SQL, Server, field, strAllFields

'Declare the SQL statement that will query the database
SQL = "SELECT * FROM dbo.User_DISC"
'other sql statements
'SQL = "SELECT DISTINCT * FROM dbo.User_Name0 ORDER BY User_Name0 DESC"

'Create an instance of the ADO connection and recordset objects
Set Connection = CreateObject("ADODB. Connection")

Set Recordset = CreateObject("ADODB.Recordset" )

'Open the connection to the database
Connection.Open "DSN=test;UID=MySCCMAccount;PWD= LetMeIn99$;Database=CM_001"

'Open the recordset object executing the SQL statement and return records
Recordset.Open SQL,Connection

'Determine whether there are any records
If Recordset.EOF Then
    WScript.echo "There are no records to retrieve; Check that you have the correct SQL query."
Else
'if there are records then loop through the fields
Do While NOT Recordset.Eof
    'What I want to return
    field = Recordset("User_Name0")
    'return more than one column
    'field = Recordset("first_name") & ", " & Recordset("first_name")
    'Store all returned values into a string
    if field <> "" then
        strAllFields = chr(13) & field + strAllFields
    end if
    Recordset.MoveNext
Loop
End If

'Display all values
msgbox "Username " & chr(13) & chr(13) & strAllFields

'Close the connection and recordset objects to free up resources
Recordset.Close

Set Recordset=nothing

Connection.Close

Set Connection=nothing

 

Notes

Batch – Reboot Computer if Up Time Greater than 5 Days

email me

This is how you would use day-in-year (like 272/365) to judge whether or not a computer has been rebooted in the last 5  days. To make the comparison, I use WMIC OS GET LASTBOOTUPTIME and WMIC OS GET LOCALDATETIME, with some DTS translation. So, it’s basically (today’s day-in-year) minus (uptime day-in-year) = x.

Screenshot

Computer up for 14 days

Computer was rebooted today

 

Script

@echo off
setlocal EnableDelayedExpansion
title Computer Reboot
cls

echo Reboot if computer has greater than 5 up days
echo.
echo Subtracts Up Time from Today, using day in year
echo.
echo.



::UP TIME
::returns timestamp in long format - not very usable as is
for /f %%A in ('WMIC OS GET LASTBOOTUPTIME ^| find "."') DO set DTS=%%A
::return day in year of up time date
call :SUB1
set DayInYear1=%dayYear%

::TODAY
::returns timestamp in long format - not very usable as is
for /f %%B in ('WMIC OS GET LOCALDATETIME ^| find "."') DO set DTS=%%B
::return day in year of today
call :SUB1
set DayInYear2=%dayYear%


::MATH
set Bool=NO
echo DayInYear1: %DayInYear1%
echo DayInYear2: %DayInYear2%
echo Math: %DayInYear2% - %DayInYear1% = X
:: do the math between days in year
set /A Answer=%DayInYear2%-%DayInYear1%
echo How many days since last reboot: %Answer%
echo.
:: if greater than 5, REBOOT computer
if %Answer% GTR 5 set Bool=YES
echo Reboot computer? %bool%

echo.
pause

if %bool% EQU YES goto SUB2

exit

:SUB1
:: RETURN DAY IN YEAR
:: Check end of month days
set /A i=0, daySum=0
for %%C in (31 28 31 30 31 30 31 31 30 31 30 31) do (
   set /A i+=1
   set /A dayCount[!i!]=daySum, daySum+=%%C
)
::uses DTS, long timestamp to extrapolate discrete elements
set /A month=1%DTS:~4,2%-100, day=1%DTS:~6,2%-100
set /A yMOD4=%DTS:~0,4% %% 4
set /A yMOD100=%DTS:~0,4% %% 100, yMOD400=%DTS:~0,4% %% 400
set /A dayYear=!dayCount[%month%]!+day
::checking feb for day 29
if %month% gtr 2 (
::checks for leap year
if %yMOD4% equ 0 set /A dayYear+=1
if %yMOD400% neq 0 if %yMOD100% equ 0 set /A dayYear-=1
)
endlocal & set dayYear=%dayYear%
GOTO:EOF

:SUB2
::RUN SHUTDOWN
:: 900 seconds = 15 minutes
start "" shutdown -r -f -t 900 -c "Please save any open work. Your computer will restart in 15 minutes for weekly scheduled maintenance."
exit

SCCM – PowerShell – Modify ADRs Deadline Time

email me

In recent SCCM builds, Microsoft has introduced Automatic Deployment Rules (ADR’s) which have the ability to automatically approve updates and deploy them. You use this method for deploying monthly updates, along with some third party updates. It’s a nice enhancement, the only problem is…there are so many windows to click through, just to find out some settings aren’t available after the initial creation of the rule (Microsoft, say it ain’t so). PowerShell can get around that. Using PS, you can make direct changes to the ADR right from ISE or the PS console.

 
The Script

[CmdletBinding()]
param(
[parameter(Mandatory=$true)]
$SiteServer,
[parameter(Mandatory=$true)]
$SiteCode,
[parameter(Mandatory=$true)]
[int]$CreationTimeDays,
[parameter(Mandatory=$true)]
[int]$DeadlineDays,
[parameter(Mandatory=$true)]
[ValidateScript({$_.Length -eq 4})]
$DeadlineHours
)
 
$CurrentDate = (Get-Date).AddDays(-$CreationTimeDays).ToShortDateString()
$Deadline = ([System.Management.ManagementDateTimeConverter]::ToDmtfDateTime((Get-Date).AddDays($DeadlineDays))).Split(".").SubString(0,8)[0]
$Time = "$($DeadlineHours)00"
 
$ADRClientDeployment = Get-WmiObject -Namespace "root\sms\site_$($SiteCode)" -Class SMS_UpdateGroupAssignment -ComputerName $SiteServer
foreach ($Deployment in $ADRClientDeployment) {
    $CreationDate = $Deployment.ConvertToDateTime($Deployment.CreationTime).ToShortDateString()
    $DeploymentName = $Deployment.AssignmentName
    if ($CreationDate -gt $CurrentDate) {
        Write-Output "Deployment to be modified: `n$($DeploymentName)"
        try {
            $Deployment.EnforcementDeadline = "$($Deadline)$($Time).000000+***"
            $Deployment.Put() | Out-Null
            if ($?) {
                Write-Output "`nSuccessfully modified deployment`n"
            }
        }
        catch {
            Write-Output "`nERROR: $($_.Exception.Message)"
        }
    }
}

 

Script Name: Change-ADRTime.ps1

Parameters:

  • SiteServer
    Should be a NetBIOS or FQDN of your site server
  • SiteCode
    Enter the site code of the specified site server
  • CreationTimeDays
    The number specified here will determine what deployments will be modified depending on the creation time of each deployment
  • DeadlineDays
    Specify a number of days ahead you would want the new installation deadline time to be
  • DeadlineHours
    Specified in 4 digits, e.g. “1400” is equal to 02:00 PM. It’s important that you specify value for this parameter within quotations

Let’s say that we’d want to change the installation deadline time to 5 days ahead, at 01:00 PM and only on the deployments created yesterday.
Command Line

As an SCCM Admin, run

.\Change-ADRTime.ps1 -SiteServer sccm.DOMAIN.com -SiteCode 001 -CreationTimeDays 1 -DeadlineDays 5 -DeadlineHours "1300"

WQL

email me

Windows Management Instrumentation (WMI) is the Microsoft implementation of WBEM, an industry initiative that attempts to facilitate system and network administration. WMI was introduced with Windows 2000, and has since evolved to include data about the most Windows resources, both hardware and software.

There are several ways in which you can access WMI data, and most of them use WQL queries. You can use several tools to execute WQL queries, the most accessible of which is a tool called WMI Tester (wbemtest.exe) – it is installed with Windows.

This article is a short tutorial that attempts to shed some light on several WQL aspects through a series of example WQL queries. I grouped the queries by their type.

  • Object Queries
  • Event Queries
  • Schema Queries

Most of the queries presented here will get all WMI object properties (e.g., Select * …) in order to make the queries more readable. If you are familiar with SQL, you are probably aware of the recommendation that you should never use Select * (unless you really need all the columns) in order to make queries more efficient. I haven’t been able to confirm that selecting only specific properties has any impact on query efficiency in WQL, but you can easily replace * with property names.

WMI Tester (Wbemtest.exe) is a tool that provides the basic functionality for executing WQL queries. You can run it by typing ‘wbemtest.exe‘ in the Run box.

This opens the WMI Tester.

You first need to connect to the WMI namespace that contains the class you want to query (Root\Cimv2 in most cases). Click the Connect button.

Run the query by clicking the ‘Query’ or ‘Notification Query’ button

Enter the query text.

Click the ‘Apply’ button. This opens a window with the query results:

If the query is invalid, you will receive an error message.

 

Object Queries

Object queries are used to get information about system resources.


Query text:

Select * From Win32_Process

WMI namespace: Root\Cimv2.

Comment:

This is probably the WQL query most often found in various WMI articles and textbooks. It simply gets all the instances of a WMI class named Win32_Process which represents Windows processes. If you are interested in the properties of Win32_Process, see here.


Query text:

Select * From Win32_Process 
Where ProcessId = 999

WMI namespace: Root\Cimv2.

Comment:

If you don’t really want all Windows processes, you can qualify your query using the WHERE clause. This clause looks like this:

Where PropertyName Operator PropertyValue

where Operator is one of the WQL relational operators. The above query will return Win32_Process instances with process ID equals to 999.


Query text:

Select * From Win32_Process 
Where Priority > 9

WMI namespace: Root\Cimv2.

Comment:

One of the WQL relational operator is ‘>’ (greater than). The above query returns all Win32_Process instances with Priority greater than 9.


Query text:

Select * From Win32_Process 
Where WriteOperationCount < 10000

WMI namespace: Root\Cimv2.

Comment:

This query returns all Win32_Process instances where the WriteOperationCount is less than 10000.


Query text:

Select * From Win32_Process Where ParentProcessId <> 999
Select * From Win32_Process Where ParentProcessId != 999
Select * From Win32_Process Where Not ParentProcessId = 999

WMI namespace: Root\Cimv2.

Comment:

All three queries return Win32_Process instances where ParentProcessId is not equal to 999.


Query text:

Select * From Win32_Service

WMI namespace: Root\Cimv2.

Comment:

Another commonly seen query that retrieves all information about Windows Services. See here for details about the Win32_Service class. Note that this query returns all class instances. Sometimes this is just what you want, other times it is not, and yet other times, this is something you should definitely avoid.


Query text:

Select * From Win32_Service 
Where Name = "MSSQL$SQLEXPRESS"

WMI namespace: Root\Cimv2.

Comment:

Here is an improved query – it returns only Win32_Service instances that have the Name property equal to “MSSQL$SQLEXPRESS”. It happens that Name is the key property for the Win32_Service class, so the returned WMI object collection will have 0 or 1 item, but in general, if you qualify a query with a WMI class property value, you get all class instances where the property matches the entered value.

Query text:

Select * From Win32_Service 
Where DisplayName = "Plug and Play"

WMI namespace: Root\Cimv2.

Comment:

Here is a caveat. If you are familiar with Windows services, you know that you can access service information using Services.msc (Start > Run > Services.msc). When you open that applet, the text in the Name column is not equal to the Win32_Service.Name value. It is equal to the Win32_Service.DisplayName property value, so if you want to get services by their Services Control Panel applet name, use the above query.


Query text:

Select * From Win32_Service 
Where PathName = "C:\\WINDOWS\\system32\\inetsrv\\inetinfo.exe"

WMI namespace: Root\Cimv2.

Comment:

Here is another caveat. If a property value contains backslashes, you need to escape them by putting another backslash before (or after) each of them – otherwise, you get the ‘Invalid query’ error.


Query text:

Select * From Win32_Service 
Where Name Like "%SQL%"

WMI namespace: Root\Cimv2.

Comment:

What if you don’t know the exact service name (or display name)? This is where the LIKE WQL operator comes in handy. Just like in SQL, the ‘%’ meta character replaces any string of zero or more characters, so this query returns all Win32_Service instances where the Name property contains the string “SQL”.


Query text:

Select * From Win32_Service 
Where Name > "M" And Name < "O"

WMI namespace: Root\Cimv2.

Comment:

You can use all WQL operators with string properties. This query returns all Win32_Service instances whose Name is greater than ‘M’ or less than ‘O’. The usual string comparison rules apply.


Query text:

Select * From Win32_Service 
Where ExitCode = "1077"

WMI namespace: Root\Cimv2.

Comment:

The Win32_Process.ExitCode property type is UInt32, but it is enclosed in quotes. WMI will does its best to interpret a string value and convert it to an appropriate type. This doesn’t work the other way – with string properties, you have to use quotes.


Query text:

Select * From Cim_DataFile 
Where Drive = "C:" 
And Path = "\\Scripts\\"

WMI namespace: Root\Cimv2.

Comment:

Cim_DataFile is a WMI class with which you should definitely always use the WHERE clause. ‘Select * From Cim_DataFile’ alone can take hours to complete, because it will return all files on your computer. Note that the Path property doesn’t contain file names or the drive letter which is stored in the Drive property.


Query text:

Associators Of {Win32_NetworkAdapter.DeviceId=1}

WMI namespace: Root\Cimv2.

Comment:

As you can see, Select queries are not the only query type in WQL. Just like Select queries, Associators Of queries can return either WMI objects or class definitions. There is a difference though: Select queries always return a collection of instances of one WMI class, or at least instances of classes that have the same parent class at some level. Associators Of queries, on the other hand, usually return a collection of WMI objects that belong to different WMI classes. One thing that the returned objects have in common is that they are all associated with the WMI object specified in the Associators Of query (enclosed between the curly braces). Note that you have to use the key properties of an object to specify its path, and that there are no spaces between the property name, the equals sign, and the property value. The above query returns instances of the following classes:

  • Win32_ComputerSystem
  • Win32_DeviceMemoryAddress
  • Win32_IRQResource
  • Win32_NetworkAdapterConfiguration
  • Win32_NetworkProtocol
  • Win32_PnPEntity
  • Win32_PortResource
  • Win32_SystemDriver

Query text:

Associators Of {Win32_NetworkAdapter.DeviceId=1} 
Where ResultClass = Win32_NetworkAdapterConfiguration

WMI namespace: Root\Cimv2.

Comment:

Most of the time, you will not need all WMI objects associated with a WMI object. You can narrow the returned collection by specifying the class of the returned objects in an Associators Of query Where clause. The above query returns an instance of Win32_NetworkAdapterConfiguration associated with the source object.


Query text:

Associators Of {Win32_NetworkAdapter.DeviceId=1} 
Where AssocClass = Win32_NetworkAdapterSetting

WMI namespace: Root\Cimv2.

Comment:

WMI classes are associated by a special type of WMI classes, called association classes. Win32_NetworkAdapterand Win32_NetworkAdapterConfiguration objects are associated by instances of the association class called Win32_NetworkAdapterSetting. As you can see, you can also use association class names to limit the returned object collection.


Query text:

References Of {Win32_NetworkAdapter.DeviceId=1}

WMI namespace: Root\Cimv2.

Comment:

You can use a References Of query to examine WMI object associations. Unlike Associators Of queries, References Of queries return only WMI association classes. This query returns instances of the following WMI association classes:

  • Win32_AllocatedResource
  • Win32_NetworkAdapterSetting
  • Win32_PnPDevice
  • Win32_ProtocolBinding
  • Win32_SystemDevices

Event Queries

Event queries are used for WMI event subscriptions.

Query text:

Select * From __InstanceCreationEvent 
Within 5 
Where TargetInstance Isa "Win32_Process"

WMI namespace: Root\Cimv2.

Comment:

This query is also often found in WMI samples. WMI event queries are different from other query types in that they don’t return WMI objects immediately. Instead of that, they are used for subscribing to WMI events, and objects are returned as events arrive. Note the two distinctive characteristics of event queries not present in other query types: the Within clause and the __InstanceCreationEvent class. The Within clause tells WMI how often to poll for events in seconds. In the above query, the polling interval is 5 seconds. WQL event monitoring consumes system resources, so it is important to balance between the need to get events on time and the need not to burden the system. The __InstanceCreationEvent class is one of the classes used only in event queries (other two commonly used classes are  __InstanceModificationEvent and  __InstanceDeletionEvent). An instance of this class is created when a requested event arrives. The __InstanceCreationEvent.TargetInstance property holds a reference to a WMI class that actually triggered the event. In the above query, it is the Win32_Process class, and we can use the TargetInstance property to access its properties.


Query text:

Select * From __InstanceCreationEvent 
Within 5 
Where TargetInstance Isa "Win32_Process" 
And TargetInstance.Name = "Notepad.exe"

WMI namespace: Root\Cimv2.

Comment:

This query monitors the process creation event but only for processes named ‘Notepad.exe’.


Query text:

Select * From __InstanceDeletionEvent 
Within 5 
Where TargetInstance Isa "Win32_Process" 
And TargetInstance.Name = "Notepad.exe"

WMI namespace: Root\Cimv2.

Comment:

Use this query to monitor process deletion events for processes whose Name property is equal to ‘Notepad.exe’. A process deletion event occurs when a process exits. There is one thing you should note about a query like this: if you open Notepad and then quickly close it (within less than 5 seconds), it is possible for WMI to miss that and not report it as an event.


Query text:

Select * From __InstanceModificationEvent 
Within 5 
Where TargetInstance Isa "Win32_Process" 
And TargetInstance.Name = "Notepad.exe"

WMI namespace: Root\Cimv2.

Comment:

This query monitors Win32_Process modification events, not the process modification event. This is an important distinction – if the Windows process entity has a property that is not represented with a Win32_Process WMI class, and if that property changes, WMI will not report the change. Only Win32_Processproperty changes are returned as WMI events.


Query text:

Select * From __InstanceOperationEvent 
Within 5 
Where TargetInstance Isa "Win32_Process" 
And TargetInstance.Name = "Notepad.exe"

WMI namespace: Root\Cimv2.

Comment:

This query monitors all three types of events: creation, deletion, and modification events. The __InstanceOperationEvent class is the parent for the __InstanceCreation__InstanceDeletion, and __InstanceModification classes, and you can use this fact to subscribe to all three event types at the same time. The __InstanceOperationEvent class is abstract (which means that it doesn’t have instances), so the actual event class returned by an event is one of the tree instance classes, and you can find out which one by inspecting its __Class system property. This way, you can determine the event type.


Schema Queries

Schema queries are used to get information about WMI itself and its structure.


Query text:

Select * From Meta_Class

WMI namespace: Any.

Comment:

This is the most basic schema query. You can connect to any WMI namespace and use this query to get all the classes present in it. Meta_Class is a meta class used only in schema queries.


Query text:

Select * From Meta_Class 
Where __Class = "Win32_LogicalDisk"

WMI namespace: Root\Cimv2.

Comment:

This query uses the __Class system property to get the Win32_LogicalDisk class. Schema queries don’t return class instances, but class definitions, and a query like this will return a class definition regardless of whether there are any instances. Why would you want to get a class definition? New WMI classes are added for every new Windows version, and a query like this can check if a class exists on a system.


Query text:

Select * From Meta_Class 
Where __Superclass Is Null

WMI namespace: Any.

Comment:

WMI is organized hierarchically – there is a hierarchy of namespaces as class containers, and there is a hierarchy of classes within each namespace. There is only one top level namespace called ‘Root’, but there is always more than one top level class in a namespace (even when you create a new empty namespace, a number of system WMI classes are created automatically). You can use this query to get all top level classes for a namespace. (This query also works if you use ‘=‘ instead of ‘Is‘.)


Query text:

Select * From Meta_Class 
Where __Superclass = "Win32_CurrentTime"

WMI namespace: Root\Cimv2.

Comment:

For each WMI class, the __Superclass property holds the name of its immediate parent class. You can use this query to return all immediate children classes of a class. Note the quotes around the class name. __Superclassis one of the seven WMI system properties (see details here), and you can use them in schema queries. All except one – the __Dynasty property is a string array, and you can’t use array properties in WQL queries. The above query returns two classes: Win32_LocalTime and Win32_UTCTime, the immediate children of Win32_CurrentTime.


Query text:

Select * From Meta_Class 
Where __Dynasty = "Cim_Setting"

WMI namespace: Root\Cimv2.

Comment:

__Dynasty is another WMI system property – for each class, it holds the name of the top level class from which the class is derived. This query will return all children of Cim_Setting, a top level class situated in the Root\Cimv2 namespace.


Query text:

Select * From Meta_Class 
Where __Class Like "Win32%"

WMI namespace: Root\Cimv2.

Comment:

All WMI classes belong to a schema (or at least they should). For example, classes whose name begins with ‘Cim’ belong to the Cim schema, a group of ‘core and common’ WMI classes defined by DMTF. Classes that begin with ‘Win32’ belong to the ‘Win32’ schema – these classes are derived from Cim classes and extend them. You can use this query to list all classes that belong to the ‘Win32’ schema. The query uses the Like operator – this means, it can’t be used on Windows versions earlier than Windows XP, because the Like operator was added to WQL for XP.


Query text:

Select * From Meta_Class 
Where __This Isa "__Event"

WMI namespace: Any.

Comment:

This is not an event query despite the fact that it uses the __Event class. It is a schema query that lists all child classes (both direct and indirect) of __Event. Note the use of ‘__This’, a special WMI property used in schema queries, and the ‘Isa’ operator.

SCCM – Install Distribution Point on Workgroup Member Server

email me

These steps detail how to add a DP role to a workgroup, a non-domain, non-trusted computer.

NOTE: Microsoft said this could not be done.


From Microsoft…

 

From MVP…

 

Microsoft Training Session…

I was even in a SCCM training session with Microsoft and they said, no, a distribution point would not operate in a workgroup. If that was true, then explain this workgroup computer (server) set up with the DP role, receiving packages, and having the ability to service local workstations at the site. And, just note, I moved this out of the lab and have implemented it in production; it works fine.

1 – The machine named workgroup…in the workgroup of workgroup.

2 – Showing the content was successfully distributed to workgroup.

3 – The device’s IP address with time stamp.


moving on…

 

The Steps


On Workgroup Computer

Create and Add local sccm service account to local admin group (my example): SCCMAdmin

 

Update Local Resolution Files

At c:\windows\system32\drivers\etc

hosts
10.1.0.99 YourSCCMServer.DOMAIN.com
10.1.0.99 YourSCCMServer

lmhosts (required to set up the SLP)
10.1.0.99 YourSCCMServer #PRE
10.1.0.99 “SMS_SLP \0x1A” #PRE
10.1.0.99 “MP_001 \0x1A” #PRE

 

Install CM Client

Copy CM setup files to c:\Windows\ccmsetup

C:\Windows\ccmsetup\ccmsetup.exe /SOURCE:C:\Windows\CCMSetup SMSSITECODE=001 /MP:YourSCCMServer.DOMAIN.COM

For testing, make sure firewall is off. You will eventually want to open ports 135 and 445.


On the SCCM Server

At c:\windows\system32\drivers\etc

update hosts file
workgroup_computer_IP       computer_name

 

On the Workgroup Computer

Wait until the CM client has installed successfully.

Verify this reg key exists and populated with your SCCM server:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\CCM
string SMSSLP   value YourSCCMServer.DOMAIN.com

For features, verify or install IIS, BITS, BranchCache, WDS, RDC
—just use defaults to continue and install

Reboot if required.

 

On the SCCM Server

Create and Add local sccm service account to local admin group (my example): SCCMAdmin

Open SCCM Console, navigate to Administration > Site Configuration > Servers and Site System Roles

Create Site System Server

Enter IP Address for FQDN

Select site code from the drop down

Use %computername%\SCCMAdmin for account (literally type in %computername%—with %)

Add Distribution Point

Select Install and configure IIS if required by configuration manager

Select Enable and configure BranchCache for this DP

Enter Description: Server name

Select Allow clients to connect anonymously

Do not enable pull content (not supported with untrusted/workgroups)

Add respective local boundary group per site

While logged in as SCCMAdmin on SCCM server, navigate to \\IP_Address\ADMIN$, if prompted, enter and save credentials.

SCCM will set up the DP. It will take time; several hours, depending upon the connection. MS uses pauses, waits, and drizzle time, meaning…it isn’t fast. Note, BITS can be modified on the Client Settings in SCCM, but you really need to know what you’re doing.

Monitor distmgr.log and PkgXferMgr.log…wait for the successes to roll in.

After success messages stop appearing (this usually means the content has been synced), verify the SCCM content library is populated on the Workgroup computer.

Then, test a package deploy and/or portal package pull. View deployments under monitoring.

Bask in the glory of doing the impossible…

SCCM – How to Rebuild NAL

email me

This is how to rebuild the NAL or Network Abstraction Layer.

1. Stop SMS_Site_Component_manager and SMS_Executive Service.

2. Add a registry key: HKLM\SOFTWARE\WOW6432node\Microsoft\Nal\Server\Providers

3. Add a Reg_Multi_SZ value under it. The name should be “Active Order”

4. Input the value: LOCAL MSWNET NWNDS NWBIND

5. Open command line window. Go to the SCCM installation path. By default it will under “\Program files (x86)\Microsoft Configuration Manager\bin\i386” folder.

6. Run following command line: regsvr32 abnwsvr.dll regsvr32 falsvrn.dll regsvr32 mslmsvrn.dll

7. After all the .dll is registry successfully, there will be 2 new values generated under the Active Order.

8. Close the SCCM console if it is opened. Go to Control Panel > Programs and Features > select Configuration Manager > select Repair.

9. Restart server.

10. Upon restart, open the CM.

 
Notes

SMS_DistributionPoint Server WMI Class

 

To view the NALPATH:

Open registry.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SMS\DP

Key NALPath

PowerShell – Working with User Accounts

email me

This post details some of the user account basics, such as removing a user from a group, and deleting a user account from the local computer.

# Computer name
$ComputerName = $env:COMPUTERNAME

# User to remove
$User = "JDoe"

# Group name to remove user from
$GroupName = "Administrators"

# ---------------

$ADObject = [ADSI]("WinNT://$ComputerName,computer")
$Group = $ADObject.PSBase.Children.Find("$GroupName")

$ErrorActionPreference = "SilentlyContinue"
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null

# return members of admin group
Get-WmiObject Win32_Group -Filter "LocalAccount=True" | foreach { $_.Name }
Write-Host ""

# Remove from admin group
$Group.Remove("WinNT://$User") 
Write-Host "Removed $User from $GroupName"
Write-Host ""

# Delete account from computer
$ADObject.Delete('User',$User)
Write-Host "Deleted $User from $ComputerName"
Write-Host ""

$ComputerName = ""
$User = ""
$ADObject = ""
$Group = ""
$GroupName = ""

 

Notes

Get_ADUser

ADS_USER_FLAG_ENUM enumeration

#list users in domain admins group
Get-ADGroupMember -identity "domain admins" | Get-ADUser -Property DisplayName | Select Name

#list all user account properties
Get-ADUser username -Properties * | Select *

#remove a list of users
ForEach ($User in (Get-Content "C:\_PowerShell\users.txt"))
{ $Group.Remove("WinNT://$User")
}

#multiple computers
$ComputerNames = "PC1","PC2","PC3","PC4"

#Disable Account
$newuser.userflags.value = $newuser.UserFlags.value -BOR $Disabled
$newUser.SetInfo()

#Enable Account
$newuser.userflags.value = $newuser.UserFlags.value -BXOR $Disabled
$newUser.SetInfo()

#Force Change
$newUser.PasswordExpired = 1
$newUser.SetInfo()

$Computername = $env:COMPUTERNAME
$ADSIComp = [adsi]"WinNT://$Computername"
$ADSIComp.Delete('User','UserToDelete')

#Create password
$Password = Read-Host -Prompt "Enter password for $Username" -AsSecureString
$BSTR = [system.runtime.interopservices.marshal]::SecureStringToBSTR($Password)

#Set password on account
$_password = [system.runtime.interopservices.marshal]::PtrToStringAuto($BSTR)
$NewUser.SetPassword(($_password))
$NewUser.SetInfo()

#Cleanup
[Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
Remove-Variable Password,BSTR,_password

SCCM – Rebuild WMI

email me

@echo off
cls
sc config winmgmt start= disabled
net stop winmgmt /y
%systemdrive%
cd %windir%\system32\wbem
for /f %%s in ('dir /b *.dll') do regsvr32 /s %%s
wmiprvse /regserver
winmgmt /regserver
sc config winmgmt start= auto
net start winmgmt
for /f %%s in ('dir /s /b *.mof *.mfl') do mofcomp %%s
pause

SCCM – Package is showing Content Distribution ‘In Progress’

email me

I had a problem where I would distribute packages to DPs, but not all DPs would receive the content.

The problem was because the Remote Differential Compression feature in Windows Server was not enabled (could be BITS for you). Add the feature from the Server Manager console and then wait. Review the distmgr.log and it should show that the content has been distributed.

Another issue that you may have if there are missing ‘required’ services:

distmgr.log: Package #AXC00001 does not have a preferred sender.

 
The moral of the story? Make sure all the required services are installed and running.