Browsed by
Category: Uncategorized

Windows Azure Pack PowerShell sample commands – Get Commands

Windows Azure Pack PowerShell sample commands – Get Commands

Over the past 12 months I’ve been working less on SCCM and more in Windows Azure Pack, to help integrate a complex database as a service solution. One of the things I have found over this time is there is limited information around how to automate using PowerShell, along with quite a number assumptions made in provided documentation. To this end I have spent a couple of hours writing out some useful PowerShell commands to obtain the commonly used settings of a Azure Pack environment for example the websites and ports which go with each of the websites. I’ll note that while the native Azure Pack PowerShell can obtain this information on a WAP express install, it doesn’t return the information in a dispersed configuration which is the recommended deployment for production usage of Azure Pack. So I have written up the following code to help out everybody.

# query SQL function

function Invoke-SQL {

param([string] $connstring,[string] $sqlCommand)

$connectionString = $connstring

$connection = new-object system.data.SqlClient.SQLConnection($connectionString)

$command = new-object system.data.sqlclient.sqlcommand($sqlCommand,$connection)

$connection.Open()

$adapter = New-Object System.Data.sqlclient.sqlDataAdapter $command

$dataset = New-Object System.Data.DataSet

$adapter.Fill($dataSet) | Out-Null

$connection.Close()

$dataSet.Tables

}

 

# get WAP connection string

$connstring = (Get-MgmtSvcSetting -Namespace adminsite | where {$_.name -eq ‘ApplicationServicesConnectionstring’}).value

$connstring = $connstring.Split(‘;’)[0] + ‘;’ + $connstring.Split(‘;’)[1] + “; Integrated Security=SSPI”

 

# get WAP websites

$adminsite = (Invoke-SQL -sqlCommand “SELECT value FROM [Config].[Settings] where Namespace = ‘AdminSite’ and Name = ‘Authentication.Fqdn'” -connstring $connstring).value

$TenantSite = (Invoke-SQL -sqlCommand “SELECT value FROM [Config].[Settings] where Namespace = ‘TenantSite’ and Name = ‘Authentication.Fqdn'” -connstring $connstring).value

$AuthSite = (Invoke-SQL -sqlCommand “SELECT value FROM [Config].[Settings] where Namespace = ‘AuthSite’ and Name = ‘Authentication.Fqdn'” -connstring $connstring).value

$windowsauthsite = (Invoke-SQL -sqlCommand “SELECT value FROM [Config].[Settings] where Namespace = ‘WindowsAuthSite’ and Name = ‘Authentication.Fqdn'” -connstring $connstring).value

$AdminAPI = (Invoke-SQL -sqlCommand “SELECT value FROM [Config].[Settings] where Namespace = ‘AdminSite’ and Name = ‘Microsoft.Azure.Portal.Configuration.OnPremPortalConfiguration.RdfeAdminUri'” -connstring $connstring).value

$TenantAPI = (Invoke-SQL -sqlCommand “SELECT value FROM [Config].[Settings] where Namespace = ‘TenantSite’ and Name = ‘Microsoft.Azure.Portal.Configuration.AppManagementConfiguration.RdfeUnifiedManagementServiceUri'” -connstring $connstring).value

$ClientRealm = (Invoke-SQL -sqlCommand “SELECT value FROM [Config].[Settings] where Namespace = ‘AdminSite’ and Name = ‘Authentication.RelyingParty'” -connstring $connstring).value.Split(‘,’)[1].replace(‘”Realm”:”‘,).replace(‘”‘,)

 

# Check is cert is signed

$admin = $adminsite.Split(‘:’)

$cert = !(New-Object System.Net.Security.SslStream((New-Object System.Net.Sockets.TcpClient($admin[1].Replace(‘/’,),$admin[2])).GetStream())).IsSigned

 

# get token

$token = Get-MgmtSvcToken -AuthenticationSite $windowsauthsite -ClientRealm $ClientRealm -Type Windows -DisableCertificateValidation:$cert

 

# get admin users

Get-MgmtSvcAdminUser -ConnectionString $connstring.Replace(“PortalConfigStore”,“Store”)

 

# get users

Get-MgmtSvcUser -AdminUri $AdminAPI -Token $token -DisableCertificateValidation:$cert

 

# get plans

Get-MgmtSvcPlan -AdminUri $adminapi -Token $token -DisableCertificateValidation:$cert

 

# get Subscriptions

Get-MgmtSvcSubscription -AdminUri $AdminAPI -Token $token -DisableCertificateValidation:$cert

*make sure you check the quotes when copying the PowerShell commands

While this isn’t an exhaustive list of commands it covers off the basics which will get anybody new to the platform and PowerShell a leg up to obtain the information of the solution.

You will note that I’m using SQL queries to obtain the websites and ports as I found it was more robust to complete the process this way.

Good luck

Steve

Get SCCM 2012 R2 Application Deep link

Get SCCM 2012 R2 Application Deep link

So over the weekend i was reviewing some posts up on the Facebook groups for SCCM and i can across this blog around sharing a link to the AppCatalog which also references this blog which details the actual creation of the application string. Which for me looks great as it resolves a big bug bear i have had where i couldn’t share the link to customers, a comment on the Blog post questioned where the right click tool was for this, which got me thinking i can do that.

I’ve added a few lines of code to Nick’s code which gets the encoded string, pops up a new draft email from Outlook (sorry if you have notes. no no really I’m so so sorry if you have to live with lotus notes) along with Copying the string to the clip board.

The added code is:

function
sendemail([string]$appstring,[string]$appnamestring)
{
$ol = New-Object –comObject Outlook.Application

$mail = $ol.CreateItem(0)

$mail.BodyFormat = 2

$mail.Subject = “How to Install $appnamestring

$mail.Body = $appstring

$mail.save()

$inspector = $mail.GetInspector

$inspector.Display()
}
$appname = $args[0]
Import-Module ($env:SMS_ADMIN_UI_PATH).Replace(“i386”, “ConfigurationManager.psd1”)$sitecode = ((gwmi –Namespace root\ccm –Class SMS_Authority).Name.split(“:”)[1])
Set-Location $SiteCode“:\”
$scopeidlong = (Get-CMApplication –Name $appname).CI_UniqueID
$scopeid = $scopeidlong.split(“/”)[0] + “/” +$scopeidlong.split(“/”)[1]
$encoded = encode($scopeid)
$appcat = (gwmi –Namespace root\ccm\LocationServices –Class SMS_PortalInformation).Url
$encoded = $appcat + “/#/SoftwareCatalog/AppDetails/” + $encoded
sendemail $encoded $appname
Add-Type –AssemblyName ‘System.Windows.Forms’
[Windows.Forms.Clipboard]::SetText($encoded)

The first part of the script is a function to create an email, then we handle the Arguments coming into the script and launch, and importing the SCCM 2012 PowerShell module from your computer. Then we get the sitecode and connect to path.

Now we are connected to your site in PowerShell we will get the CI_UniqueID for the application you are looking for, which is then split to remove the version number off the end, then we Encode the string using Nick’s code which we then get the AppCatalog’s URL to provide a full path for the email which is created next, then copies the code to ClipBoard.

So I have created a simple zip file which you can download from my OneDrive here

Please let me know if you find any issues.

Enjoy

Steve

Technorati Tags: SCCM,Self Service,AppCatalog

Actual Installed Application Reporting from SCCM

Actual Installed Application Reporting from SCCM

Having worked on SCCM for many years now I have lost count of how many times I have been asked, “Since you guys have an agent on all of the computers can I get you to provide me a list of ALL software that is installed on all of the computers?” after which there is a long draw out discussion explaining that when SCCM returns the information from Programs and Features it doesn’t discriminate between System install applications which are not visible in Programs and Features in which you will typically end up with double the amount of applications per computer, then what actually appears in Programs and Features. To this end I’ve had some spare time recently, so I have done some investigating, and found that with a simple update of the MOF we can typically get within +/-98% accuracy of only the applications that appear in Programs and Features appearing in the SCCM reports, which for me it a huge win.

As we know the Registry is the master of what appears in the Programs and Features list, so for example you can change the Display Name of applications in Programs and Features by changing the following registry Item:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\<Application Identifier>|DisplayName

This Key also includes such things as the Publisher, Version numbers, and Uninstallation strings. The Item’s which we are interested in for this solution are the following:
    SystemComponent
    ParentDisplayName

The SystemComponent item will appear as 1 if the application is to be hidden from Programs and Features, so for example the SCCM Client will have SystemComponent = 1 which appears to hide it from Programs and Features, if this item is not defined it is assumed to be a 0 (This is also used by Microsoft Office to hide each of the components from Programs and Features).

Whereas the ParentDisplayName item is used for patches to applications and Operating system, an example of can be seen in Windows XP where you could select the check box to hide updates. When not referring to the install Operating System it will refer to the DisplayName of the parent, for example “Microsoft .NET Framework 4 Client Profile” will have all of the updates that are dependent upon it.

Now we have explained what we are doing and why let’s step through the process of actually capturing the details in SCCM.

  1. Browse to \\<SCCMSERVER>\SMS_<SITECODE>\inboxes\clifiles.src\hinv
  2. Copy Configuration.mof to c:\data\mofs
  3. Open Configuration.mof with Notepad
  4. Find the Follow:
    class Win32Reg_AddRemovePrograms
    {
    [key]
    string ProdID;
    [PropertyContext(“DisplayName”)]
    string DisplayName;
    [PropertyContext(“InstallDate”)]
    string InstallDate;
    [PropertyContext(“Publisher”) ]
    string Publisher;
    [PropertyContext(“DisplayVersion”)]
    string Version;
    }
    and Replace with the following:
    class Win32Reg_AddRemovePrograms
    {
    [key]
    string ProdID;
    [PropertyContext(“DisplayName”)]
    string DisplayName;
    [PropertyContext(“InstallDate”)]
    string InstallDate;
    [PropertyContext(“Publisher”) ]
    string Publisher;
    [PropertyContext(“DisplayVersion”)]
    string Version;
    [PropertyContext(“SystemComponent”)]
    string SystemComponent;
    [PropertyContext(“ParentDisplayName”)]
    string ParentDisplayName;
    }

  5. Then find the following directly below:
    class Win32Reg_AddRemovePrograms64
    {
    [key]
    string ProdID;
    [PropertyContext(“DisplayName”)]
    string DisplayName;
    [PropertyContext(“InstallDate”)]
    string InstallDate;
    [PropertyContext(“Publisher”) ]
    string Publisher;
    [PropertyContext(“DisplayVersion”)]
    string Version;
    }
    and Replace with the following:
    class Win32Reg_AddRemovePrograms64
    {
    [key]
    string ProdID;
    [PropertyContext(“DisplayName”)]
    string DisplayName;
    [PropertyContext(“InstallDate”)]
    string InstallDate;
    [PropertyContext(“Publisher”) ]
    string Publisher;
    [PropertyContext(“DisplayVersion”)]
    string Version;
    [PropertyContext(“SystemComponent”)]
    string SystemComponent;
    [PropertyContext(“ParentDisplayName”)]
    string ParentDisplayName;
    }

  6. Close and Save Configuration.mof
  7. In an elevated command prompt run the following commands:
    1. Mofcomp c:\data\configuration.mof
      the result should look like this:
  8. Browse back to: \\<SCCMSERVER>\SMS_<SITECODE>\inboxes\clifiles.src\hinv and rename the existing file to match this naming convention:
    1. configurationYYYYMMDD.mof
  9. Copy configuration.mof from c:\data to \\<SCCMSERVER>\SMS_<SITECODE>\inboxes\clifiles.src\hinv
  10. Open SCCM 2012 Console and browse Administration à Client Settings
  11. Right click on Default Client Settings and select Properties
  12. Select Set Classes under the Hardware Inventory tab on the Default Settings Form
  13. Select Export on the Hardware Inventory Classes form
  14. Save the exported file to c:\data\export.mof
  15. Open C:\data\export.mof in notepad
  16. Find the following:
    class Win32Reg_AddRemovePrograms : SMS_Class_Template
    {
    [SMS_Report (TRUE), key ]
    string ProdID;
    [SMS_Report (TRUE) ]
    string DisplayName;
    [SMS_Report (TRUE) ]
    string InstallDate;
    [SMS_Report (TRUE) ]
    string Publisher;
    [SMS_Report (TRUE) ]
    string Version;
    };

    and replace with:
    class Win32Reg_AddRemovePrograms : SMS_Class_Template
    {
    [SMS_Report (TRUE), key ]
    string ProdID;
    [SMS_Report (TRUE) ]
    string DisplayName;
    [SMS_Report (TRUE) ]
    string InstallDate;
    [SMS_Report (TRUE) ]
    string Publisher;
    [SMS_Report (TRUE) ]
    string Version;
    [SMS_Report (TRUE) ]
    string SystemComponent;
    [SMS_Report (TRUE) ]
    string ParentDisplayName;
    };

  17. Then find the following directly below:
    class Win32Reg_AddRemovePrograms64 : SMS_Class_Template
    {
    [SMS_Report (TRUE), key ]
    string ProdID;
    [SMS_Report (TRUE) ]
    string DisplayName;
    [SMS_Report (TRUE) ]
    string InstallDate;
    [SMS_Report (TRUE) ]
    string Publisher;
    [SMS_Report (TRUE) ]
    string Version;
    };

    and replace with:
    class Win32Reg_AddRemovePrograms64 : SMS_Class_Template
    {
    [SMS_Report (TRUE), key ]
    string ProdID;
    [SMS_Report (TRUE) ]
    string DisplayName;
    [SMS_Report (TRUE) ]
    string InstallDate;
    [SMS_Report (TRUE) ]
    string Publisher;
    [SMS_Report (TRUE) ]
    string Version;
    [SMS_Report (TRUE) ]
    string SystemComponent;
    [SMS_Report (TRUE) ]
    string ParentDisplayName;
    };
  18. Close and Save c:\data\export.mof
  19. On the Hardware Inventory Classes form select Import
  20. Review the Message to ensure everything is correct, and Select Import.
  21. On the Hardware Inventory Classes form search for Win32reg_addremoveprograms and ensure that SystemComponent & ParentDisplayName are selected, then click on OK, and OK, back to the SCCM Console

To test ensure that you have completed a Policy refresh on a targeted computer, wait a few minutes then trigger a hardware inventory, you can see if the policy has updated by reviewing the InventoryAgent.log on the client computer and filter with CMTrace for Win32reg_addremoveprograms, you should see something like this:

And on the server side you can confirm the new inventory has been loaded by reviewing the DataLdr.log file on the Site server, looking for the line
“Done: Machine=<Computername>(GUID:<ComputerGUID>) code=0 (1473 stored procs in <InventoryMIF>.MIF)”
to ensure that the data has been loaded into the SQL database.

From here we can create a report using the following example SQL query:
Count of all applications installed on all computers:

SELECT
*
FROM
(

SELECT
DISTINCT

v_GS_ADD_REMOVE_PROGRAMS_64.DisplayName0 AS “Product Name”, v_GS_ADD_REMOVE_PROGRAMS_64.Publisher0 AS “Publisher”,
count(*)
as
‘Install count’

FROM v_GS_ADD_REMOVE_PROGRAMS_64

INNER
JOIN v_R_System_Valid ON v_R_System_Valid.ResourceID = v_GS_ADD_REMOVE_PROGRAMS_64.ResourceID

JOIN v_GS_OPERATING_SYSTEM ON v_GS_ADD_REMOVE_PROGRAMS_64.ResourceID = v_GS_OPERATING_SYSTEM.ResourceID

WHERE v_GS_ADD_REMOVE_PROGRAMS_64.SystemComponent0 is
null
and v_GS_ADD_REMOVE_PROGRAMS_64.parentdisplayname0 is
null
and
not v_GS_ADD_REMOVE_PROGRAMS_64.Displayname0 is
null

group
by v_GS_ADD_REMOVE_PROGRAMS_64.DisplayName0, v_GS_ADD_REMOVE_PROGRAMS_64.Publisher0

UNION ALL

(


SELECT
DISTINCT

v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 AS “Product Name”, v_GS_ADD_REMOVE_PROGRAMS.Publisher0 AS “Publisher”,count(*)
as
‘Install count’


FROM v_GS_ADD_REMOVE_PROGRAMS


INNER
JOIN v_R_System_Valid ON v_R_System_Valid.ResourceID = v_GS_ADD_REMOVE_PROGRAMS.ResourceID


JOIN v_GS_OPERATING_SYSTEM ON v_GS_ADD_REMOVE_PROGRAMS.ResourceID = v_GS_OPERATING_SYSTEM.ResourceID


WHERE v_GS_ADD_REMOVE_PROGRAMS.SystemComponent0 is
null
and v_GS_ADD_REMOVE_PROGRAMS.parentdisplayname0 is
null
and
not v_GS_ADD_REMOVE_PROGRAMS.Displayname0 is
null

    group
by v_GS_ADD_REMOVE_PROGRAMS.DisplayName0, v_GS_ADD_REMOVE_PROGRAMS.Publisher0

))
AS u

ORDER
BY “Product Name”, Publisher

Installed applications on a Single Computer:

DECLARE @compname VARCHAR(MAX) = ‘Computer Name’

SELECT
*
FROM
(

SELECT
DISTINCT

v_GS_ADD_REMOVE_PROGRAMS_64.DisplayName0 AS “Product Name”, v_GS_ADD_REMOVE_PROGRAMS_64.Publisher0 AS “Publisher”, v_GS_ADD_REMOVE_PROGRAMS_64.Version0 AS “Version”

FROM v_GS_ADD_REMOVE_PROGRAMS_64

INNER
JOIN v_R_System_Valid ON v_R_System_Valid.ResourceID = v_GS_ADD_REMOVE_PROGRAMS_64.ResourceID

JOIN v_GS_OPERATING_SYSTEM ON v_GS_ADD_REMOVE_PROGRAMS_64.ResourceID = v_GS_OPERATING_SYSTEM.ResourceID

WHERE v_GS_ADD_REMOVE_PROGRAMS_64.SystemComponent0 is
null
and v_GS_ADD_REMOVE_PROGRAMS_64.parentdisplayname0 is
null
and
not v_GS_ADD_REMOVE_PROGRAMS_64.Displayname0 is
null

and v_R_System_Valid.Netbios_Name0 = @compname

UNION ALL

(


SELECT
DISTINCT

v_GS_ADD_REMOVE_PROGRAMS.DisplayName0 AS “Product Name”, v_GS_ADD_REMOVE_PROGRAMS.Publisher0 AS “Publisher”, v_GS_ADD_REMOVE_PROGRAMS_64.Version0 AS “Version”


FROM v_GS_ADD_REMOVE_PROGRAMS


INNER
JOIN v_R_System_Valid ON v_R_System_Valid.ResourceID = v_GS_ADD_REMOVE_PROGRAMS.ResourceID


JOIN v_GS_OPERATING_SYSTEM ON v_GS_ADD_REMOVE_PROGRAMS.ResourceID = v_GS_OPERATING_SYSTEM.ResourceID


WHERE v_GS_ADD_REMOVE_PROGRAMS.SystemComponent0 is
null
and v_GS_ADD_REMOVE_PROGRAMS.parentdisplayname0 is
null
and
not v_GS_ADD_REMOVE_PROGRAMS.Displayname0 is
null

and v_R_System_Valid.Netbios_Name0 = @compname

))
AS u

ORDER
BY “Product Name”, Publisher

You will notice that we are not using the “v_add_remove_programs” view, this appears to be a derived view which doesn’t appear to be updated when new columns added to the Class, but we can get around this by using the Union function in SQL.

Good Luck

Steve

User Query Tool

User Query Tool

For the past few years I have been working on and implementing a solution (User Query Tool) for the Desktop and Service Desk Teams that will allow for the discovery of the Computer Name simply by entering in a Username, or Serial Number (into the UQT).

Initially UQT was much customised to match the environment which it was built for, but over time I have been removing these deep integration points, along with moving the queries from the simple SQL queries which I ported from SQL reports with hardcoded server connection strings in the early version of the tool, to what I’ve made available today, using dynamically detected SMS Provider connections that can be used in most environments without modifications.

You can download the tool from here

How to use the User Query Tool, so when the tool starts up it will look something like this:

A list of domains which are available in your environment in the dropdown list, which is a mash up of the user’s domains from the SMS Provider & the list of DNS suffix’s on your network adaptors. This is to ensure that it’s a relevant list as both lists by themselves tend to have domains/computer names which will blow out the list. If you don’t see your domain in the list don’t fret, just type it into the field when you complete your search and it should discover the user you have searched for.

When searching on the username you can use partial matches of the username field in Active Directory. For example, I can search for user ‘hoskings’, by typing in the whole name or I can just type in ‘hosk’.

It will return all of the usernames which contain the search string, so if there was hoskings, hoskings-a, and hoskingp it would return all 3 of them which I can then select the account in question.

It is worth noting at this point that it will only return any accounts which have details associated with them, so you will only see relevant information. In future versions though, I might introduce the ability to search Active Directory first for all users which match, but this solution allows for handling of users which exist in domains you might not have access to, along with ensure that you get a fast result.

Once you have selected the user object it will complete the search for computers which the user has logged onto. For multiple computers it will return a list like this:

From here we can select the computer which is the closest match in this case we are going to use StevesRig, which we double click on and you get the following results:

If you double click on each of the text fields it will copy the information into the Clipboard for ease of use, along with the Copy All Results button which is intended to be used for lodging of tickets into your ticketing system as it contains all of the pertinent information required for when logging a ticket.

You will see in the above images that the other buttons are greyed out, they will enable when the tool can either communicate to the computer or Active Directory for the user section. Each of the of buttons do exactly what they say they do J

Please let me know if you have any feedback around this tool, you can see the code for the application at this link: https://uqt.codeplex.com/

Troubleshooting like a Boss (not a real Boss tho)

Troubleshooting like a Boss (not a real Boss tho)

Recently I have been doing some informal training sessions with some junior staff members and realised that there is quite a few things we do in the this industry that can be very hard to pick up without prompting from the guys that have been around for a while. As such I figured I would take a few hours and detail some of the processes I use to troubleshoot issues.

From a troubleshooting point of view, let’s review a scenario that recently I have been involved in resolving.

Scenario:

When logging on to a computer post ADMT on a few computers we were receiving the follow error message when attempting to log onto the computer with an account that hadn’t previously logged onto the computer:

User Profile Service Service Failed the logon. User Profile cannot be loaded

When this came to me there had already been 2 tech’s looking into this error, and were blaming it on the Domain migration, we could log onto the machine as Local administrator and I could connect remotely to it via the SCCM 2012 Remote tools.

Trouble Shooting Steps:

The first steps to investigate this issue would be to start in the event log, I know it sounds daunting to look in the event log it’s huge and there is so much information in there, which is exactly why this is perfect for the task at hand.

We looked in the Security event log and there was no issues with the computer or the user authenticating, right away at a high level we can start ruling out the ADMT component of the changes to the system, as there would be authentication issues between the machine and the domain if there was.

We then moved to the Application event log and right away we started seeing warning events like this every time a new user attempts to logon:

Windows cannot copy file C:\Users\Default\AppData\Local\Microsoft\Windows Live\SqmApi\SqmData720896_00.sqm to location C:\Users\Guest\AppData\Local\Microsoft\Windows Live\SqmApi\SqmData720896_00.sqm. This error may be caused by network problems or insufficient security rights.

DETAIL – Access is denied.

And:

Windows cannot find the local profile and is logging you on with a temporary profile. Changes you make to this profile will be lost when you log off

And:

Windows cannot copy file C:\Users\Default\AppData\Local\Microsoft\Windows Live\SqmApi\SqmData720896_00.sqm to location C:\Users\TEMP\AppData\Local\Microsoft\Windows Live\SqmApi\SqmData720896_00.sqm. This error may be caused by network problems or insufficient security rights.

DETAIL – Access is denied.

And:

Windows cannot log you on because your profile cannot be loaded. Check that you are connected to the network, and that your network is functioning correctly.

DETAIL – Only part of a ReadProcessMemory or WriteProcessMemory request was completed.

So we browse to “C:\Users\Default\AppData\Local\Microsoft\Windows Live\SqmApi” and sure enough when we looked at the permissions on SqmData720896_00.sqm we found that the user’s security group didn’t have access to the file thus it was causing the User Profile Service to fail as it couldn’t copy this file into the new user profile nor the Temp profile. Once the permissions we replicated from the parent folder the issue was resolved. I know it sounds simple when you see it like this, but this whole troubleshooting took around 20-30 minutes, with much searching around the internet and discussion with the techs on site to find out the extent of the issue and alike, and keeping them informed throughout the trouble shooting phase.

Wrap up:

The biggest piece of advice I can provide anybody just starting out and wanting to impress around there troubleshooting ability, is to use the KISS method,

K eep

I t

S imple

S tupid

Always think that the simplest answer is the correct one, this methodology can be used for creating the fix for the issue, if it’s for the issue above where it was impacting lest than 5 users it doesn’t make sense to script or even automate the issue, this is something that you hand the solution back to the support teams with the comment if you see this issue check this event message and confirm it is the exact issue then run the remediation steps. If this issue was impacting a large percentage of my fleet I would look at creating a fix to remediate it proactively, be it with a simple Group Policy as this one could be covered with, or a compliance setting from SCCM it can be automated if need be.

In the heat of an issue it can be very hard to keep calm especially when you need to be able to quickly and confidently rule out idea even if everybody else working on the issue keeps pointing at that being the issue, I recommend setting your IM to Busy or Do Not Disturb so only the people you can control the flow of information coming in, let’s face it being told for the 10th time that there are users unable to logon to their computers gets a bit grating when you are trying to focus on how you are going to resolve the issue, in saying that being able to bounce ideas of co-workers is just as invaluable as they might have made a change to the system or alike that you are not aware of.

The next thing to start looking at is the log files be it the event log or application specific logs, now days most good applications log almost everything, this is where you will find out more information about the goings on of your system then randomly clicking around the OS to try to just resolve the issue like a lot of admins now days do so often, with the goal of, I just have to fix the issue and if I try this it might fix the problem. In some cases you can resolve or at least Band-Aid a solution by doing this, but it normally takes a lot longer to come to the root cause and in most cases you don’t know the root cause as you have just found the fix and moved on to the next fire. I can’t say that logs will provide the answer for everything problem but it is a fantastic place to start.

Another simple thing you can do if the machine is blue screen is to get the Debug tool kit from Microsoft for you OS and run the dump check application over the memory.dmp/mini.dmp file which typically will return the offending component of the OS just confirm dates before you do it as it might have been from a blue screen 2 weeks/months/years earlier.

I know a lot of what I’m saying is common sense to most of us but the number of people I deal with now days that gloss over these troubleshooting steps it staggering, the other thing that makes a great troubleshooter is somebody who has the confidence to sit there and state their case and back it up, there is no point working out the problem, then raising the ticket to a senior resource without a hand over because you are not quite sure about the answer. The senior resources have typically made it to those roles because they have back themselves and ask the right questions to build trust with the management teams.

Good Luck and Happy trouble shooting,

Steve

Extended Active Directory Attributes from Orchestrator

Extended Active Directory Attributes from Orchestrator

ADExtPublic OIP download

So we have just implemented a new VoIP Phone system and we found that on occasion we would get errors where disabled users object would still have the ipPhone attribute populated with a number that had been reassigned. To report back on this is pretty simple by using the SCCM user object discovery, but to how do we automate a solution to do something with the details. We ended up settling on using System Centre Orchestrator, as it allows us to be a little bit more flexible then a script.

So I got to work creating an OIP, and in the end I created 3 custom Activities, which are “”, “” and “” detailed below.

Obtain Custom Properties:

This one is quite simple in its use, you define the String Attibute for the user object that you want returned and it will return it.
Inputs:

Distinguished Name:  This is the Distinguished Name of the user.
Property Name: This is the name of the Attribute that you want returned.

Outputs:

Property result: This is the Value of the Attribute for the desired user.

Obtain ipPhone:

The result of this activity is the same as the Obtain Custom Properties activity, just hard set to the ipPhone attribute.

Inputs:

Distinguished Name:  This is the Distinguished Name of the user.

Outputs:

ipPhone: This is the Value of the ipPhone attribute for the desired user.

Remove ipPhone:

This Activity is a little more destructive, it will actually clear the ipPhone attribute for the defined user object.

Inputs:

Distinguished Name:  This is the Distinguished Name of the user.

Outputs:

IPPhone removal result: Result of “Success” or “did not exist”

As you can see below the scripts for this OIP is pretty simple.

ADUserExtended.cs

using Microsoft.SystemCenter.Orchestrator.Integration;namespace ADUserExtended
{
[Activity(“Obtain Custom Properties”)]
public class ADExtendedCustProp
{
private string usercust;
[ActivityInput(“Distingished Name”)]
public string Usercust
{
set { usercust = value; }
}
private string propname;
[ActivityInput(“Property Name”)]
public string Propname
{
set { propname = value; }
}
[ActivityOutput(“Property result”)]
public string PropResult
{
get { return defineProp.getcustprop(usercust, propname); }
}
}
[Activity(“Obtain ipPhone”)]
public class ADExtendedipPhone
{
private string userip;
[ActivityInput(“Distingished Name”)]
public string Userip
{
set
{
userip = value;
}
}
[ActivityOutput(“ipPhone”)]
public string IPPhone
{
get { return checkphone.GetIPphone(userip); }
}
}
[Activity(“Remove ipPhone”)]
public class ADExtendedremove
{
private string userrem;
[ActivityInput(“Distingished Name”)]
public string Userrem
{
set
{
userrem = value;
}
}
[ActivityOutput(“IPPhone removal result”)]
public string IPPhonerem
{
get { return removeipPhone.remIPphone(userrem); }
}
}
}

 DefineProps.cs

using System.DirectoryServices;namespace ADUserExtended
{
class defineProp
{
public static string getcustprop(string userId, string Propname)
{
using (var userEntry = new DirectoryEntry(@”LDAP://” + userId))
{
if (userEntry.Properties.Contains(Propname))
{
return userEntry.Properties[Propname][0].ToString();
}
else
{
return “did not exist”;
}
}
}
}
}

CheckPhones.cs

using System.DirectoryServices;namespace ADUserExtended
{
public class checkphone
{
public static string GetIPphone(string userId)
{
using (var userEntry = new DirectoryEntry(@”LDAP://” + userId))
{
if (userEntry.Properties.Contains(“ipPhone”))
{
return userEntry.Properties[“ipPhone”][0].ToString();
}
else
{
return string.Empty;
}
}
}
}
}

RemoveipPhone.cs

using System.DirectoryServices;namespace ADUserExtended
{
class removeipPhone
{
public static string remIPphone(string userId)
{
using (var userEntry = new DirectoryEntry(@”LDAP://” + userId))
{
if (userEntry.Properties.Contains(“ipPhone”))
{
userEntry.Properties[“ipPhone”].Clear();
userEntry.CommitChanges();
userEntry.Close();
return “success”;
}
else
{
return “did not exist”;
}
}
}
}
}

Good Luck

Steve