Quantcast
Channel: TCSMUG - Twin Cities Systems Management User Group - Sherry Kissinger
Viewing all 45 articles
Browse latest View live

SCCM ConfigMgr 2012 R2 SP1 Error creating CTM job (0x80070003)

$
0
0

Issue:  After upgrading Configmgr 2012 R2 CU4 clients to ConfigMgr 2012 R2 SP1 clients, some, but not all, clients started having issues downloading content.  It seemed to only happen on clients which just so happened to be our Management Points, or our Software Update Points, so likely this particular error won't be seen much.  But in looking for the keywords of "error creating CTM job", where the error code was 0x80070003, there wasn't anything I could find via any popular search engine. 

Symptoms:  In those clients' local ContentTransferManager.log if you didn't have debuglogging enabled, it was simply this error, repeated every time a download request was attempted:

Error creating CTM job (0x80070003)

If one turned on debuglogging, you got a little bit more information, but not much:

In CContentTransferManager::DownloadContentEx7 Directory::Exists(szDestPath), HRESULT=80070003 (e:\nts_sccm_release\sms\framework\ccmctm\ctmanager.cpp,390) Error creating CTM job (0x80070003)

In those clients' local CAS.log, you'd see this error:

CcmContentTransferManager:DownloadContent failed with error 0x80070003

Diagnosis:  80070003, that error, is supposed to mean something like "the system cannot find the path specified".  We wondered if it was because many of these clients happened to be Management Points, so their installed location for the CM Client wasn't %windir%\ccm, but was <drive letter>:\SMS_CCM.  But that didn't make sense, only some of them were like that, others were in %windir%\ccm.  What it ended up being was a confused (or corrupt) ccmcache folder.

Fix:  Since this is about downloading into cache, and 8007003 is supposed to mean "can't find the path", we moved the location of ccmcache, temporarily (using the Control Panel applet).  What is "supposed" to happen is that when you do that, the former location should be automatically deleted.  That did NOT happen--so clearly something was messed up with it.  Deleted the old location manually, and then put the cache location RIGHT BACK to the normal cache location.  And then content can download.


Configuration Manager 2012, the Client Reinstalls Daily

$
0
0

Symptoms: Clients reinstall the ConfigMgr Client on a daily basis, and it doesn't appear that any automated push, automated deployment, or technician is reinstallng the client. In the %windir%\ccmsetup log, the reinstall is successful (exit code of 0) but yet the client reinstalls over and over again, seemingly automatically.

Cause: At some point in time in the client's past, a scheduled task called "Configuration Manager Client Retry Task", was created on purpose to retry a failed client install. However, once the client was successfully installed, that scheduled task was not (for some reason), and is not, being removed. No matter how many times the client reinstalls successfully.

Fix: Manually, go look at scheduled tasks, and delete that task. Automatically, you can import the attached Configuration Item --> Here <--, and deploy it (by adding it to a Baseline, and deploying that Baseline with the checkbox to allow remediation) to find and remove the scheduled task.

This Configuration Item may not be the best answer for your environment; it's up to you to determine if this Configuration Item is required, and to which collection of machines you want to target.  One suggestion could be to create a collection of "clients with the latest version in your environment (whatever that is)". The theory being that if those clients have the latest version, if they are a healthy enough client to find the policy for this baseline deployment, and they are already the latest client version--why retry reinstalling the CM Client? It's clearly installed and working... so... the SchTask clearly isn't actually needed, if it's there.  Of course, YOU will need to remember to change the collection's query whenever your client version increments; so that you are targeting the correct clients; for your environment.

Mark Cochrane's RegKeyToMof 3.3a

Visual Studio Editions via ConfigMgr MOF Edit

$
0
0

This ask came up recently, so I did a bit of research.  It is NOT, I repeat NOT perfect, and NOT complete.  I did NOT include all of the possible "Team" editions for Visual Studio 2005 or Visual Studio 2008. But for Visual Studio 2010, 2012, 2013, and (I think) 2015, the editions should be reported correctly. If you want to (need to) add in all of the potential "team" editions for Visual Studio 2005/2008, you can use this as a guide and add in all the additional columns for those.

If you're familiar with the "DotNetFrameworks" mof edits, it's similar to that type of MOF edit.  --> attached <--, are what you would add to the bottom of your configuration.mof file in <installed location>\inboxes\clifiles.src\hinv, and the snippet you would import into your "Default Client Settings", hardware inventory, and then enable, or create a custom client agent setting to enable it only to a specific collection of machines.

Using a sql query like this, you can then pull out the "highest" Edition.

select
sys1.netbios_name0 as 'computername',
vised.version0 as 'Visual Studio Version',
case when vised.ultimate0 = 1 then 'Ultimate'
  when vised.Enterprise0 = 1 then 'Enterprise'
  when vised.Premium0 = 1 then 'Premium'
  when vised.Professional0 = 1 then 'Professional'
  when vised.Community0 = 1 then 'Community' end as 'Highest Edition Installed'
from v_gs_visualstudioeditions0 vised
join v_r_system sys1 on sys1.resourceid=vised.resourceid
where ( vised.professional0 is not null or vised.premium0 is not null or
        vised.ultimate0 is not null or vised.standard0 is not null or
        vised.community0 is not null or vised.enterprise0 is not null
)
and vised.version0 in ('2005','2008','2010','2012','2013','2015')
order by sys1.computername, vised.version0

which could help you make a report like that could look like this. Computer names have been changed, but note that Computer3 and Computer5 have two versions of Visual Studio, and then their editions:
VisualStudioEditions

Sources for where I got these regkeys:

for Visual Studio 2005: http://blogs.msdn.com/b/heaths/archive/2006/12/17/detecting-visual-studio-2005-service-pack-1.aspx
  There may be more subkeys for Team System, but I didn't grab them..
for Visual Studio 2008: http://blogs.msdn.com/b/heaths/archive/2009/05/29/detecting-visual-studio-2008-service-pack-1.aspx
   There's a WHOLE bunch of VSDB, VSTA, VSTD, VSTS, VSTT for all the team System 2008 editions
for Visual Studio 2010: http://blogs.msdn.com/b/heaths/archive/2010/05/04/detection-keys-for-net-framework-4-0-and-visual-studio-2010.aspx
    Note, Ultimate replaces Team Suite
for Visual Studio 2012: http://blogs.msdn.com/b/heaths/archive/2012/08/03/detection-keys-for-visual-studio-2012.aspx
for Visual Studio 2013: Couldn't find a direct link, but found a note that there's Professional, Premium, and Ultimate, so guessing it's these. And data comes back from clients, so appears to work.
for Visual Studio 2015: http://blogs.msdn.com/b/heaths/archive/2015/04/13/detection-keys-for-visual-studio-2015.aspx
   Note, Enterprise replaces premium and ultimate

 

Gather some Adobe Serial Numbers and Version using ConfigMgr Compliance Settings and Hardware Inventory

$
0
0

Update to an older blog entry...

http://www1.myitforum.com/2012/06/13/gather-some-adobe-software-serial-numbers-using-configmgr-dcm-and-hardware- inventory/ :

Because this thread: http://social.technet.microsoft.com/Forums/en-US/configmgrinventory/thread/7243fac9-36c4- 4d1f-9b2b-eb1b2f53ed87, got me thinking about it, I went to the adobe blog entry they referenced, here: http://blogs.adobe.com/oobe/2009/11/software_tagging_in_adobe_prod_1.html

Searched our lab for a couple of clients with full Adobe products, and low and behold… found the .swtag files mentioned. Interestingly, that blog was a little misleading–it didn’t seem to cover some of the tags that are really in the .swtag files for serial number, version, etc… so I doubt the script (attached) will actually find everything. but it’s a start; so I thought I’d throw this out into the wild (blog it) and see what others can make of it.

Attached is a script, which you’d run similar to the "all members of all local groups" type of thing–run it on clients (either as a recurring advertisement or as a DCM ConfigItem, with no validation), and the sms_def.mof edit to pull the info back into your DB. Some of what it returns you’ll already have from ARP (name, version), but the golden nuggets of info are the SerialNumber, and whether it’s part of a Suite (according to that blog, anyway). There’s also something about "licensedState", but one of my test boxes had a serial number, but said it was unlicensed. Not sure what that is really about–that the human didn’t click on something after launching to register online? Not sure. But hey, that field is there if it means anything. You could always set that to FALSE in the mof if that LicenseState information is pointless.

What was nice about the above routine was that in the "partofasuite" returned results, it would say "Std" or "Pro" right in there, so that when the licensing folk would come knocking and ask for your pro vs std counts, it was relatively easy to run a report, and show them exactly what you had out there, based on Adobe's own information. With the "DC" version, they've apparently decided to make it even MORE difficult to tell the difference between Pro vs. Std.

Here's a new link to their swid tag information: http://www.adobe.com/devnet-docs/acrobatetk/tools/AdminGuide/identify.html

Fortunately, the Script + Mof edit will pull back all of the information necessary to tell the difference, it just makes reports more, uh... "fun"

http://www.adobe.com/devnet-docs/acrobatetk/tools/AdminGuide/identify.html#identifying-dc-installs

and basically you'll see that that std, the serial numbers start with 9101 and for pro, the serial numbers start with 9707

Here's a sample report, once you've created the ConfigItem and Baseline, deployed it, and imported the mof snippet into inventory, and start getting back results:

This sample report is ONLY for Acrobat, there are other Adobe products returned with the AdobeInfo routine, so this is just a sample report, it's not meant to showcase everything returned.

;with cte as (
Select distinct resourceid, Case when a.SerialNumber0 like '9101%' then 'Std'
when a.SerialNumber like '9707%' then 'Pro' end as 'Type',
Case when a.PartOfASuite0 like 'v7%' then 'DC'
when a.PartOfASuite0 like 'v6%' then '11'
when a.PartOfASuite0 like 'Acrobat%' then '10' end as 'Version'
from v_gs_AdobeInfo0
where a.PartOfASuite0 like 'v%{}Acrobat%' or a.PartOfASuite0 like 'Acrobat%'
)
select cte.version as [Acrobat Version] , cte.type as [Acrobat Type] ,count(*) as 'Count'
from cte group by [version], [type]
order by [version], [type]
would result in something sorta like this (#'s have been changed from my production environment to fake #'s)
Acrobat Version Acrobat Type Count
10                    Pro                20
10                    Std                15
11                    Pro                300
11                     Std               210
DC                   Pro                700
DC                   Std                800
Of course, the best part of this routine is *if* Adobe comes knocking, you can show them that the information about pro vs. std originates from their SWID tag files, and you can point to their web site about how to tell the difference, so they should be satisfied and quickly leave you alone (unless, of course... you did deploy Pro to all of your environment, and you thought you were deploying Standard... well, then... pay up...)

--> Link --< to get the mof file for importing for ConfigMgr Inventory, and the script to add to a Configuration Item (or you could deploy it as a recurring Advertisement, if you are adverse to Configuration Baselines).  Basically, the client, on a recurring basis, needs to run the script to populate--or wipe and re-populate--the custom WMI location with the Adobe swid tag information.

Dot Net Framework Versions via Custom Hardware Inventory

$
0
0

Based on information contained in here:

http://social.technet.microsoft.com/wiki/contents/articles/15601.how-to-determine-the-net-framework-installed-versions.aspx

Below is a potential custom hardware inventory MOF edit to use to pull back installed versions of .net using Configuration Manager 2012

There's a section you would need to add to your <installed location on your server>\inboxes\clifiles.src\hinv\Configuration.mof, near the bottom.

Then there's the section you would save as a text file, called "dotnet.mof", and you would import that into via your CM Console, into "Default Client Settings", hardware inventory, import.

Once clients start reporting back, there's a potential report for you to use, with, if you just-so-happened-to-have workstations that were named starting with "WIN7-", a sample output. Obviously you can modify the "where" statement to use a @ parameter in sql, or re arrange the SQL report in whatever way is needed for your reporting requirements.

WARNING!!! Sometimes when one copies and pastes from a web browser, "straight" quotes are changed for you to "Smart Quotes". You will want to carefully look at what you've copied and pasted, and if necessary, use a notepad "replace" to replace any curly smart quotes to straight quotes.

//=================================DOTNetFrameworks

#pragma namespace("\\\\.\\root\\cimv2")
#pragma deleteclass("DotNETFrameworks",NOFAIL)
[DYNPROPS]
class DotNETFrameworks

{ [key] string Version="";
boolean Installed;
string ServicePack;
string BuildNumber;
};

[DYNPROPS]
instance of DotNETFrameworks
{ Version="1.0";
[PropertyContext("local|HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Active Setup\\Installed Components\\{78705f0d-e8db-4b2d-8193-982bdda15ecd}|Version"),Dynamic,Provider("RegPropProv")] BuildNumber;
};

[DYNPROPS]
instance of DotNETFrameworks
{ Version="1.0 MCE";
[PropertyContext("local|HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Active Setup\\Installed Components\\{FDC11A6F-17D1-48f9-9EA3-9051954BAA24}|Version"),Dynamic,Provider("RegPropProv")] BuildNumber;
};

[DYNPROPS]
instance of DotNETFrameworks
{ Version="1.1";
BuildNumber="1.1.4322";
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v1.1.4322|Install"),Dynamic,Provider("RegPropProv")] Installed;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v1.1.4322|SP"),Dynamic,Provider("RegPropProv")] ServicePack;
};

[DYNPROPS]
instance of DotNETFrameworks
{ Version="2.0";
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727|Install"),Dynamic,Provider("RegPropProv")] Installed;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727|SP"),Dynamic,Provider("RegPropProv")] ServicePack;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v2.0.50727|Version"),Dynamic,Provider("RegPropProv")] BuildNumber;
};

[DYNPROPS]
instance of DotNETFrameworks
{ Version="3.0";
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.0|Install"),Dynamic,Provider("RegPropProv")] Installed;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.0|SP"),Dynamic,Provider("RegPropProv")] ServicePack;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.0|Version"),Dynamic,Provider("RegPropProv")] BuildNumber;
};

[DYNPROPS]
instance of DotNETFrameworks
{ Version="3.5";
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5|Install"),Dynamic,Provider("RegPropProv")] Installed;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5|SP"),Dynamic,Provider("RegPropProv")] ServicePack;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v3.5|Version"),Dynamic,Provider("RegPropProv")] BuildNumber;
};

[DYNPROPS]
instance of DotNETFrameworks
{ Version="4.0";
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Client|Install"),Dynamic,Provider("RegPropProv")] Installed;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Client|SP"),Dynamic,Provider("RegPropProv")] ServicePack;
[PropertyContext("local|HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP\\v4\\Client|Version"),Dynamic,Provider("RegPropProv")] BuildNumber;
};

//===========End of section to be added to Configuration.mof

// Save the below as DotNet.mof, and import into Default Client Settings, Hardware Inventory

[ SMS_Report (TRUE),
SMS_Group_Name ("DotNetFrameworks"),
SMS_Class_ID ("DotNETFrameworks"),
Namespace ("\\\\\\\\.\\\\root\\\\cimv2") ]
class DotNETFrameworks : SMS_Class_Template
{
[ SMS_Report (TRUE), key ] String Version;
[ SMS_Report (TRUE) ] String BuildNumber;
[ SMS_Report (TRUE) ] String Installed;
[ SMS_Report (TRUE) ] String ServicePack;
};
// ========End of To-be-Imported.mof

Sample Report:

SELECT
sys1.netbios_name0 as [Computername],
MAX(CASE dn.version0 when '1.0' THEN
case dn.buildNumber0 when isnull(dn.buildnumber0,1) then dn.BuildNumber0 End END) AS [.Net 1.0],
MAX(CASE dn.version0 when '1.1' THEN
case dn.BuildNumber0 when isnull(dn.buildnumber0,1) then dn.buildnumber0 End END) AS [.Net 1.1],
MAX(CASE dn.version0 when '2.0' THEN
case dn.BuildNumber0 when isNull(dn.buildnumber0,1) then dn.BuildNumber0 end END) AS [.Net 2.0],
MAX(CASE dn.version0 when '3.0' THEN
case dn.BuildNumber0 when isNull(dn.buildnumber0,1) then dn.BuildNumber0 end END) AS [.Net 3.0],
MAX(CASE dn.version0 when '3.5' THEN
case dn.BuildNumber0 when isNull(dn.buildnumber0,1) then dn.BuildNumber0 end END) AS [.Net 3.5],
MAX(CASE dn.version0 when '3.5' THEN
case dn.ServicePack0 when isnull(DN.ServicePack0,1) then dn.ServicePack0 end END) AS [.Net 3.5 ServicePack],
MAX(CASE dn.version0 when '4.0' THEN
case dn.BuildNumber0 when isNull(dn.buildnumber0,1) then dn.BuildNumber0 end END) AS [.Net 4.0]
FROM
v_r_system_valid sys1
Left Join v_gs_dotnetframeworks0 dn
ON dn.resourceid=sys1.ResourceID
where sys1.netbios_name0 like 'Win7-%'
Group By
sys1.netbios_name0
ORDER BY
sys1.netbios_name0

The report would end up looking something sort of like this:

ComputerName   .Net 1.0  .Net 1.1   .Net 2.0               .Net 3.0               .Net 3.5            .Net 3.5 Service Pack     .Net 4.0
Win7-ABC12345   NULL     1.1.4322   2.0.50727.5420   3.0.30729.5420   3.5.30729.5420  1                                 4.5.50938
WIN7-ABC23456  NULL     1.1.4322   2.0.50727.5420   3.0.30729.5420   3.5.30729.5420  1                                 4.5.51209

.Net Frameworks 4.x updated Mof and Reports

$
0
0

This is an update to this older blog: http://mnscug.org/blogs/sherry-kissinger/422-dot-net-frameworks-mof-edit

Nash Pherson, Enterprise Client Management MVP, pointed out that for versions 4.5x and higher Microsoft is recommending using the dword registry key called "release" to better pinpoint what version of .net is installed. Because "buildNumber" in the registry will say something like "4.5.51209"--but what it MEANS is that's version 4.5.2 (don't ask me why, I don't get it either).

Unfortunately, "Release" also isn't in nice, plain English. I couldn't find anything "easy" to make using BuildNumber any more or less useful than using "Release" number. But if you want to do exactly what Microsoft tells you to use, attached are updated mof edits for reporting on .net versions. The only thing added to this is "release"; which is only applicable to .net 4.5 and higher (well, up to 4.6.1 as far as I can tell; maybe it'll still be there in newer versions as those are released, but for now, that's all I can see)

If you already have the DotNetFramework edits, you replace your existing snippet for DotNetFrameworks in your configuration.mof with the configuration.mof edit in --> This Zip File <--   If you've never edited your \inboxes\clifiles.src\hinv\configuration.mof for dotNetFrameworks yet, you will add that attached snippet to the bottom of that file. Monitor your 'dataldr.log' to confirm all is well.

Once configuration.mof is edited, you take the attached "to-be-imported-dot-net.mof" and in your CM console, Administration, Client Settings, right-click on "Default Client Settings", Properties, Hardware Inventory, "Set Classes..." then Import that to-be-imported-dot-net.mof file. If you already have one from previously, not to worry. It'll just accept the new one and modify your tables and views. Just monitor your dataldr.log to confirm all is well.
Then, of course, it's the typical waiting that one does in ConfigMgr. Just wait a while; how long depends upon how often you have hardware inventory configured to run; the # of clients you have, and other factors unique to your environment. But in a couple hours or by the next day, try running one of the reports in the attached .zip file.

Regardless of whether you have the "old" DotNetFrameworks mof edit (which doesn't have release) or are using this new one, attached in the .zip file are also some sample reports. With versions of .net 4.0-4.5.1 no longer under support, your organization may be under hightened awareness of finding and upgrading anyone with those older versions to the supported versions. For example, below is what a report might look like, using 2 of the SQL queries attached. The top one is the results of the 'SQLtoCountDotNetVersions', and bottom one would be the 'SQLToShowVersionsInYourDatabase' -- what values you have in your database will vary from company to company.

 dotnetSampleReport

Geek notes: the "how to tell what .net is installed", came from two different Microsoft articles.
As I write this blog, this covers from .net 1.0 through .net 4.6.1
For V1-4: http://social.technet.microsoft.com/wiki/contents/articles/15601.how-to-determine-the-net-framework-installed-versions.aspx
For v4-4.61: https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx

Inventory Google Chrome Extensions with ConfigMgr

$
0
0

In response to this forum post:
https://social.technet.microsoft.com/Forums/systemcenter/en-US/55b1d256-f3fb-4296-a9e6-2241cc8d4d0d/sccm-report-google-chrome-extensions

I cobbled together a VERY rough approximation of a powershell script + mof edit that MIGHT work to gather the bare minimum information.

Download the files in the -->  Attached Zip File <-- In the .zip file are two files

TestScript1.ps1  -- this is a powershell script you will need to have every ConfigMgr client you have run, presumably the ones with Google Chrome installed.  You can either deploy it as a recurring advertisement, or my favorite is to create a "Configuration Item", and deploy the script that way on a recurring basis.

ToBeImported.mof -- Once  you've had test workstations run that powershell script, AND you've confirmed that data appears on those test workstations' root\cimv2\cm_chromeExtensions, AND that data appears to be stuff you find interesting, THEN in your CM Console, Administration, Client Settings, Default Client Settings, Hardware Inventory, Import... this file.

Caveats: 
"let the buyer beware":  Read the .ps1 file--especially the top section.  the part where the author (ok, it was me) said that this was all cobbled together and is probably useless. 

1) 1 thing I noticed even with only 15 minutes worth of testing...I uninstalled Google Chrome from the test workstation.  That does NOT clear out the user profile appdata folders where "chrome extensions" are listed.  So everything was still reported.  So it is highly likely, in fact probably guaranteed, that this will in no way EVER be indicative of "Google Chrome is actually installed and working".  It's indicative of "Google Chrome was installed once and launched once for this user--sometime during the life of the computer".  It could have been installed and uninstalled within 30 minutes and never used again--but the user profile information about chrome extensions will be there.  Forever.  Welcome to user-centric nightmares (if you weren't already aware of them).  Also by the way, chrome apparently comes pre-packaged with multiple extensions so no matter what you'll have entries if any user ever launched Chrome on that workstation--even if it was immediately uninstalled.  It won't matter.

so my recommendation is *if* you think in your weeks of testing that this might be useful in some way--in reporting you will need to be extremely careful to tie the reports about chrome extensions to machines which clearly indicate that chrome is actually installed.  Or, of course--feel free to re-write this chrome extensions script to detect that before recording anything.

2) There were some extensions in the user profile folder for chrome extensions for which I couldn't figure out any way to clearly identify what it was.  Those will be labeled unknown.  You are certainly welcome to edit the script if you know how to identify those.

3) No promises of usefulness or compatibility or even functionality are implied.  I'm just tossing this out there in the hopes that someone else can make it work better.  If in fact anyone even cares about Chrome extensions. Ever.

fyi, in testing, I got this type of information on the test box:

 

 Counter   Name Version ProfilePath ScriptLastRan
 0 Google Docs 0.9 c:\users\fakeuser 3/28/2016 4:55:13 PM
 1 Google Drive 14.1 c:\users\fakeuser 3/28/2016 4:55:13 PM
 2  YouTube 4.2.8  c:\users\fakeuser  3/28/2016 4:55:13 PM
 ...  <more data>      3/28/2016 4:55:13 PM
 14  iHeartRadio 1.1.0 c:\users\anotheruser  3/28/2016 4:55:14 PM

In the above example, "fakeuser" used Chrome and never added any CUSTOM or additional extensions.  "anotheruser" using the same computer did add a custom extension for iHeartRadio.

As mentioned, only tested in a distracted way in a test environment on 1 test workstation in a lab.  This is probably horrible code, a horrible idea, and will need to be re-written from scratch.  Or.... it just might work fine.  <shrug>


ConfigMgr Inventory Share Permissions

$
0
0

Apparently the original article on this from years ago has disappeared; so here's the old info.  This was originally for Config2007; so it may be this won't work, or will have unknown results.  YOU will need to test it and confirm it does what you think you want it to do in your environment.

Reporting on the permissions applied to non-admin shares can also be queried using the attached. Using --> This Zip File <-- , that's a vbscript.  Either deploy it as a traditional old skool package/program/recurring advertisement, or leverage a Configuration Item to deploy that script . Set a recurring schedule for what makes sense in your environment.

To Be Imported into Default Client Settings, Hardware Inventory:

// <:[-<>>>>>>>>>>>Start>>-Share Permissions-<<Start<<<<<<<<<<<>=]:>

#pragma namespace("\\\\.\\root\\cimv2\\sms")
[SMS_Report(TRUE), SMS_Group_Name("Share Permissions"), SMS_Class_ID("SMS_SharePerms")]
class SMS_SharePerms : SMS_Class_Template
{
[SMS_Report(FALSE), Key] uint32 Counter;
[SMS_Report(TRUE)] boolean Allowed;
[SMS_Report(TRUE)] string ShareName;
[SMS_Report(TRUE)] string Type;
[SMS_Report(TRUE)] string Domain;
[SMS_Report(TRUE)] string TrusteeName;
};
// <:[-<>>>>>>>>>>>End>>-Share Permissions-<<END<<<<<<<<<<<<<>=]:>

Notes:
Allowed = True means the Domain/TrusteeName is granted access of Type to the ShareName
Allowed = False means the Domain/TrusteeName is denied access of Type to the ShareName

You'd write reports against the new v_gs_share_permissions0

Currently, the vbscript is limited to 500 share instances. That could be increased by editing line 78, the DIM statements.

By design, share permissions for default shares will not be reported.

Just to be clear, this routine is for Share Permissions: Read, Change, Full. This is not for NTFS permissions on files/folders contained in those shares.

Note that this routine has only had a very brief life so far in a lab environment. There may be unforeseen problems with the script.

Bypass Powershell ExecutionPolicy

$
0
0

In attempting to do some Powershell (WinRM) remote actions, specifically using  Roger Zander's Collection Commander, I came across this blog entry and thought "Awesome, already done for me!".  http://www.verboon.info/2014/12/installing-software-using-collection-commander/

And then I kept getting errors during testing, "Exception calling "Install" : ""  But it would work fine in the home lab... After much head scratching, at work we have a GPO to set Powershell ExecutionPolicy as RemoteSigned--which is good, of course.  But it threw this particular script for a loop.  In the home lab--since it is a home lab--I had set executionpolicy to unrestricted on the test box.

What I ended up doing was I found this blog post about different ways to get around a remote-signed execution policy (in a good way, not trying to do evil things):  https://blog.netspi.com/15-ways-to-bypass-the-powershell-execution-policy/

The one which was the easiest to implement for these specific needs was the "Bypassing in Script" one detailed here:
http://www.nivot.org/blog/post/2012/02/10/Bypassing-Restricted-Execution-Policy-in-Code-or-in-Script

Configuration Manager Versions Summary Report

$
0
0

I'm sure there are a dozen if not hundreds of blogs posts out there with this exact same information; just posting it mostly for myself.  If it helps someone else, great.  As of late July 2016, these are the versions (and their Marketing or public names) for the ConfigMgr Client.  It doesn't go back to SMS 1.0, or even cm07--so not as useful for "everything ever". 

But if you get "unknown" versions when you run it, you can fill in your own blanks.

SELECT COUNT(resourceID) [Count],
    Client_Version0 [Version]
, case
when client_version0 = '5.00.7711.0000' then 'ConfigMgr 2012 RTM'
when client_version0 = '5.00.7804.1000' then 'ConfigMgr 2012 SP1'
when client_version0 = '5.00.7804.1202' then 'ConfigMgr 2012 SP1 CU1'
when client_version0 = '5.00.7804.1300' then 'ConfigMgr 2012 SP1 CU2'
when client_version0 = '5.00.7804.1400' then 'ConfigMgr 2012 SP1 CU3'
when client_version0 = '5.00.7804.1500' then 'ConfigMgr 2012 SP1 CU4'
when client_version0 = '5.00.7804.1600' then 'ConfigMgr 2012 SP1 CU5'
when client_version0 = '5.00.7958.1000' then 'ConfigMgr 2012 R2'
when client_version0 = '5.00.7958.1060' then 'ConfigMgr 2012 R2 for Linux'
when client_version0 = '5.00.7958.1203' then 'ConfigMgr 2012 R2 CU1'
when client_version0 = '5.00.7958.1254' then 'ConfigMgr 2012 R2 CU1 for Linux'
when client_version0 = '5.00.7958.1303' then 'ConfigMgr 2012 R2 CU2'
when client_version0 = '5.00.7958.1401' then 'ConfigMgr 2012 R2 CU3'
when client_version0 = '5.00.7958.1501' then 'ConfigMgr 2012 R2 CU4'
when client_version0 = '5.00.7958.1604' then 'ConfigMgr 2012 R2 CU5'
when client_version0 = '5.00.8239.1000' then 'ConfigMgr 2012 R2 SP1'
when client_version0 = '5.00.8239.1203' then 'ConfigMgr 2012 R2 SP1 CU1'
when client_version0 = '5.00.8239.1301' then 'ConfigMgr 2012 R2 SP1 CU2'
when client_version0 = '5.00.8239.1403' then 'ConfigMgr 2012 R2 SP1 CU3'
when client_version0 = '5.00.8325.1000' then 'ConfigMgr 1511'
when client_version0 = '5.00.8355.1000' then 'ConfigMgr 1602'
when client_version0 = '5.00.8355.1001' then 'ConfigMgr 1602 with policyagentendpoint.dll update'
when client_version0 = '5.00.8355.1306' then 'ConfigMgr 1602 with KB3155482'
when client_version0 = '5.00.8355.1307' then 'ConfigMgr 1602 with KB3174008'
when client_version0 = '5.00.8412.1000' then 'ConfigMgr 1606'
else 'unknown' end as [Marketing Version]
  FROM dbo.v_R_System_Valid
  GROUP BY
    Client_Version0
  ORDER BY [Version] desc

there's also this way...if you don't want to deal with all those pesky cumulative updates, or hotfixes

;with cte as (select resourceid, substring(client_version0,6,4) as [Ver] from v_r_system_valid)

select Ver,
Case
when Ver = '7711' then 'ConfigMgr 2012 RTM'
when Ver = '7958' then 'ConfigMgr 2012'
when Ver = '8239' then 'ConfigMgr 2012 R2'
when Ver = '8325' then 'ConfigMgr 1511'
when Ver = '8355' then 'ConfigMgr 1602'
when Ver = '8412' then 'ConfigMgr 1606'
else 'unknown'
 end as [Version]
,Count(resourceid) [Count]
from cte
group by ver
order by ver

Bypass Powershell ExecutionPolicy

$
0
0

In attempting to do some Powershell (WinRM) remote actions, specifically using  Roger Zander's Collection Commander, I came across this blog entry and thought "Awesome, already done for me!".  http://www.verboon.info/2014/12/installing-software-using-collection-commander/

And then I kept getting errors during testing, "Exception calling "Install" : ""  But it would work fine in the home lab... After much head scratching, at work we have a GPO to set Powershell ExecutionPolicy as RemoteSigned--which is good, of course.  But it threw this particular script for a loop.  In the home lab--since it is a home lab--I had set executionpolicy to unrestricted on the test box.

What I ended up doing was I found this blog post about different ways to get around a remote-signed execution policy (in a good way, not trying to do evil things):  https://blog.netspi.com/15-ways-to-bypass-the-powershell-execution-policy/

The one which was the easiest to implement for these specific needs was the "Bypassing in Script" one detailed here:
http://www.nivot.org/blog/post/2012/02/10/Bypassing-Restricted-Execution-Policy-in-Code-or-in-Script

Configuration Manager Versions Summary Report

$
0
0

I'm sure there are a dozen if not hundreds of blogs posts out there with this exact same information; just posting it mostly for myself.  If it helps someone else, great.  As of late July 2016, these are the versions (and their Marketing or public names) for the ConfigMgr Client.  It doesn't go back to SMS 1.0, or even cm07--so not as useful for "everything ever". 

But if you get "unknown" versions when you run it, you can fill in your own blanks.

SELECT COUNT(resourceID) [Count],
    Client_Version0 [Version]
, case
when client_version0 = '5.00.7711.0000' then 'ConfigMgr 2012 RTM'
when client_version0 = '5.00.7804.1000' then 'ConfigMgr 2012 SP1'
when client_version0 = '5.00.7804.1202' then 'ConfigMgr 2012 SP1 CU1'
when client_version0 = '5.00.7804.1300' then 'ConfigMgr 2012 SP1 CU2'
when client_version0 = '5.00.7804.1400' then 'ConfigMgr 2012 SP1 CU3'
when client_version0 = '5.00.7804.1500' then 'ConfigMgr 2012 SP1 CU4'
when client_version0 = '5.00.7804.1600' then 'ConfigMgr 2012 SP1 CU5'
when client_version0 = '5.00.7958.1000' then 'ConfigMgr 2012 R2'
when client_version0 = '5.00.7958.1060' then 'ConfigMgr 2012 R2 for Linux'
when client_version0 = '5.00.7958.1203' then 'ConfigMgr 2012 R2 CU1'
when client_version0 = '5.00.7958.1254' then 'ConfigMgr 2012 R2 CU1 for Linux'
when client_version0 = '5.00.7958.1303' then 'ConfigMgr 2012 R2 CU2'
when client_version0 = '5.00.7958.1401' then 'ConfigMgr 2012 R2 CU3'
when client_version0 = '5.00.7958.1501' then 'ConfigMgr 2012 R2 CU4'
when client_version0 = '5.00.7958.1604' then 'ConfigMgr 2012 R2 CU5'
when client_version0 = '5.00.8239.1000' then 'ConfigMgr 2012 R2 SP1'
when client_version0 = '5.00.8239.1203' then 'ConfigMgr 2012 R2 SP1 CU1'
when client_version0 = '5.00.8239.1301' then 'ConfigMgr 2012 R2 SP1 CU2'
when client_version0 = '5.00.8239.1403' then 'ConfigMgr 2012 R2 SP1 CU3'
when client_version0 = '5.00.8325.1000' then 'ConfigMgr 1511'
when client_version0 = '5.00.8355.1000' then 'ConfigMgr 1602'
when client_version0 = '5.00.8355.1001' then 'ConfigMgr 1602 with policyagentendpoint.dll update'
when client_version0 = '5.00.8355.1306' then 'ConfigMgr 1602 with KB3155482'
when client_version0 = '5.00.8355.1307' then 'ConfigMgr 1602 with KB3174008'
when client_version0 = '5.00.8412.1000' then 'ConfigMgr 1606 TAP'
when client_version0 = '5.00.8412.1006' then 'ConfigMgr 1606'
when client_version0 = '5.00.8412.1007' then 'ConfigMgr 1606 with KB3180992'
else 'unknown' end as [Marketing Version]
  FROM dbo.v_R_System_Valid
  GROUP BY
    Client_Version0
  ORDER BY [Version] desc

there's also this way...if you don't want to deal with all those pesky cumulative updates, or hotfixes

;with cte as (select resourceid, substring(client_version0,6,4) as [Ver] from v_r_system_valid)

select Ver,
Case
when Ver = '7711' then 'ConfigMgr 2012 RTM'
when Ver = '7958' then 'ConfigMgr 2012'
when Ver = '8239' then 'ConfigMgr 2012 R2'
when Ver = '8325' then 'ConfigMgr 1511'
when Ver = '8355' then 'ConfigMgr 1602'
when Ver = '8412' then 'ConfigMgr 1606'
else 'unknown'
 end as [Version]
,Count(resourceid) [Count]
from cte
group by ver
order by ver

Blog series: 30 days of Intune Trial, Part 1

$
0
0

When Intune was beta, I tried a trial at the time--which was well over a year ago.  Since things change--including me--I decided to try another 30 day trial.

Back when I was looking at it over a year ago; my priority at the time was to see if it could be capable of 'fitting in' with the needs of managing a full 'pro' or 'business' version of Windows 8.  The mobile management pieces of it weren't that interesting to me; it wasn't part of the landscape for me at work, and quite honestly I didn't have personal devices to test with.  I still don't have a full range and scope of personal test devices; but tally-ho anyway!

Here's my new premise (subject to change of course--this is testing).
- Use Intune Standalone only, not hybrid to the home lab
- Get familiar with the console
- Reporting
- Policies
- Management: users or devices or combination

I know that Intune works--it clearly works fine.  It's my journey to understand how it works with my on-premise ConfigMgr background and knowledge.  I'm sure it'll be a learning curve for me.

Day 1:
Signed up for Intune 30 day trial, created the first username and password.
It asked me to sign in to https://portal.office.com, but it wasn't letting me login at first-- had to sign out of my real liveID, and then it told me the xxxx@xxxx.onmicrosoft.com account didn't exist.
Then I just made a new IE tab; and pasted in https://portal.office.com -- and without asking for a password, logged me right in.  Seems a little odd; but I suppose that was due to the liveID.

There's an online walkthrough; it told me to create a new group, but any group name I tried said "failed to add group"
Call to b__9f was not permitted with the token|$$|ContextClass=AdHoc|$$|0=b__9f|$$|

Again, not very helpful.  But after much clicking around, found that portal.office.com wasn't the right place to add a group--apparently I need to do that over on portal.azure.com; which is then available to be targeted by 'things' in manage.microsoft.com.  Seems like a lot of consoles to go to... but if I think of it in my "how does similar stuff work when on premise"--one has a console for AD users and computers, and the CM console, and other consoles--so having multiple consoles to do similar setup for Intune shouldn't surprise me.  Might also be because I *am* standalone testing, and not Azure AD / Hybrid testing.  That would be a different experience and work flow.

Created a test user; and was able to create a group, and explicitly add that test user to that group.
Created a very very basic Configuration policy for Android, and targeted that group.

End of day one... Summary:
Created 30 day trial, created a standard user, created a group with that user, created and deployed a policy to that group.

Blog series: 30 days of Intune Trial, Part 2

$
0
0

Day 2:

A nice Microsoft person contacted me directly, just to be sure I had everything I needed for this trial.  I told him yes; I'm just testing and getting familiar with it.  If I hit some horrid snag I'll just go ask in the CM forums.

The policy made yesterday for "configuration" was Android Policies; and it was targeted to a group that contained a test user, not a device grouping.

Downloaded the Company Portal on an Android phone (Samsung S4), signed in with the user account created yesterday; the one which deserves the Configuraton Policy.  That ConfigPolicy I made custom--with only 2 very easy-to-see settings. After signing in, and going through next/next/finish on the phone, confirmed the 2 changes were enforced.

Even with currently only 1 device--much of my work life is creating reports.  Over the years, I just got good at 'knowing' where in the database information was stored, and how best to extract it when parameters change.  So in Manage.Microsoft.com, there's a reporting section.  Now that I have 1 thing to look at; time to start poking about.

Created a report for "all Devices, All publishers, All Categories".  This was created at least an hour after the device got policies, but there are zero results.  Is there something additional I need to configure?  Or does this only work for certain devices, and Android isn't one of these devices?  Or is that report only for Apps as deployed by Intune--which I haven't deployed any yet.

I do see the 1 device in the "Mobile Device Inventory Reports".  So maybe it's just time--I need to wait for the device to do an inventory and send it up. 

Since I can't see any software yet in reporting, just recording the portals that I've so far had to get to:
https://portal.office.com -- Office 365
https://portal.azure.com -- to create users and usergroups for Intune standalone to leverage
https://manage.microsoft.com -- the main Intune (at least how I think of Intune) portal.

Added another mobile device--this time a Galaxy Tab 4; I'm sure it'll get the policies just fine.  I'm more curious about what I see in reports.

Just some user experience stuff, when signing into the Company Portal, the "Activate Device Administrator" lists a lot of scary-sounding permissions; but that's only because I'm so used to Android devices being unmanaged/wide open.  But I've also become jaded to the 'permissions needed' on Android since the latest updates to the Android OS.  It's kind of like click "I agree" to those legal license notifications--you just don't read them anymore.

Well, I've waited about 3 hours since having those 2 devices get policies--and still nothing in "Detected Software Reports".  I'll let them hang out overnight--maybe that's a "every xx hours" thing or something, and I'm just too impatient. 


Blog Series: 30 days of Intune Trial, Part 3

$
0
0

Still no software in the software report.  I scrounged up a Windows 10 Home Tablet, and am trying to get that registered with Intune.  I can add the account, but on the client tablet when I go to "work access" for the account, and "Enroll in to device management" it tells me that

"System Policies prevent you from connecting to a work or school account.  Contact your support person for more information.  "

So I'm the support person I'm sure--so hmm... time to Bing and Google and see what is preventing me from actually enrolling a Windows 10 Home tablet; the BYOD scenario...

And Google-fu tells me that apparently one needs to be a local Administrator.  I thought I was; but I see that once I logged into my LiveID; the Windows 10 box decided I was a standard user, not an Admin locally on the box.  Had to promote that user to an Administrator, reboot, and then I could complete the enrollment.

Now the Company Portal actually shows me things.  Still nothing in the Software report.  But the box was just enrolled.  I'll have to check on it later. 

ConfigMgr Current Branch Topic ID 611 swd State Messages flood

$
0
0

Issue:  Clients are flooding the inboxes\auth\statesys.box\incoming with state messages similar to the below.  There isn't much there to go on. The only promising thing to look for was that it's "Topic ID="611"" and Type="611".  Researching those topicid of 611 and we found nothing public, and opening a case with Microsoft provided some clues, but this was really a new issue, at least at this scale.

<?xml version="1.0" encoding="UTF-16"?>
<Report>
<ReportHeader>
<Identification>
  <Machine>
   <ClientInstalled>1</ClientInstalled>
   <ClientType>1</ClientType>
   <ClientID>GUID:0EE65490-9075-41B1-B64D-AAAAAAAAAAAA</ClientID>
   <ClientVersion>5.00.8412.1006</ClientVersion>
   <NetBIOSName>CLIENTNAMEHERE</NetBIOSName>
   <CodePage>437</CodePage>
   <SystemDefaultLCID>1033</SystemDefaultLCID>
   <Priority>5</Priority>
  </Machine>
</Identification>
<ReportDetails>
   <ReportContent>State Message Data</ReportContent>
   <ReportType>Full</ReportType>
   <Date>20170314180133.967000+000</Date>
   <Version>1.0</Version>
   <Format>1.0</Format>
</ReportDetails>
</ReportHeader>
<ReportBody>
<StateMessage MessageTime="20170314180133.857000+000" SerialNumber="18823">
  <Topic ID="611" Type="611" IDType="0" User="" UserSID=""/>
  <State ID="100" Criticality="0"/>
  <UserParameters Flags="0" Count="2">
   <Param>GUID:0EE65490-9075-41B1-B64D-AAAAAAAAAAAA</Param>
   <Param>0</Param>
  </UserParameters>
</StateMessage>
</ReportBody>
</Report>

Cause: In a ConfigMgr 1610 environment, and in 1602, 1606 versions of this were available as well, the cause of these messages is because that client is a member of a collection, where either by accident or design, that collection has the setting for "All devices are part of the same server group".  The collection contained 40% of all clients in the environment--and in our case checking the box was NOT by design--it was accidental.

What that does, is two things we observed (and others have documented 1 of them, see links below). 
1) as per one of the links below, machines in that collection may not ever patch as expected, again.  that's because it thinks it's part of a cluster, and if it's not... it's waiting for it's "turn" to patch. 
2) Every single device in that collection, once per minute, locally does two "schedule triggers", for two different things:
{00000000-0000-0000-0000-000000000111} -- which is for "Send Unsent State Message"
{00000000-0000-0000-0000-000000000116} -- which is for "State system policy bulk send low"

You'll see that over and over and over again locally on the client in SMSClientMethodProvider.log

and that apparently ends up as .swd files in the statesys box to be processed by the database, with TopicID 611, Type 611.  If it's enough devices, and it's hotfix Tuesday and lots of state messages anyway (*cough* for example *cough*)--the auth\statesys.box inbox may become backlogged, and never catch up.

Remediation:

I'm a SQL person, so using this sql query, identify the collections which have that checkbox checked--and confirm you really meant it (If you are here reading this blog post... you likely didn't mean it).  If not, uncheck the box for "All devices are part of the same server group" on the collections listed.

;with UseCluster as (select c.SiteID as [CollectionID] from CEP_CollectionExtendedProperties CEP
join collections_g c on CEP.Collectionid=c.Collectionid
where usecluster=1)
select c.*
from UseCluster
join v_collection c on c.collectionid=UseCluster.CollectionID

Links:
https://blogs.technet.microsoft.com/enterprisemobility/2016/05/16/update-1605-for-configuration-manager-technical-preview-available-now/
https://docs.microsoft.com/en-us/sccm/core/servers/deploy/install/release-notes
https://docs.microsoft.com/en-us/sccm/core/get-started/capabilities-in-technical-preview-1605#BKMK_ServerGroups
https://social.technet.microsoft.com/Forums/en-US/86783d86-0e38-4cb4-acf8-6110acc76c0e/configmgr-1602-error-0x87d006662016410010-while-installing-update?forum=configmanagersecurity

 

ConfigMgr CCMRecentlyUsedApps blank or mtrmgr.log with StartPrepDriver - OpenService Failed with Error Issue

$
0
0

Issue:  ConfigMgr Clients which should be reporting via hardware inventory "CCMRecentlyUsedApps" have nothing to report.  An analysis of the client indicates there is nothing in WMI root\cimv2\sms\ccm_recentlyusedapps TO report, and mtrmgr.log on the client contains lines like "StartPrepDriver - OpenService Failed with Error".  See --> KB3213242 <-- at Microsoft for more details.

Remediation: What worked for us was to re-register the 'prepdrv.inf', and then restart SMS Agent Host (aka ccmexec)

Before you do anything suggested below--confirm this will fix the issue you are seeing.  Login to a box or two with the issue, and from an elevated cmd prompt, run the "remediation" powershell script below.  Watch mtrmgr.log; and manually check that root/cimv2/sms select * from ccm_recentlyusedapps gets information.  Once you see info, do a hardware inventory, and confirm that box now reports information up to your database, as you expect it to.  If manually remediating works, then you can look to completing the steps below to automate the fix across your environment.

What we did to remediate the 'StartPrepDriver - OpenService Failed with Error' using a Configuration Item and Baseline was this:

It is assumed that you are using a "custom client agent setting" for enabling CCM_RecentlyUsedApps, since you normally do NOT want to target "every client".  Usually you don't want to target heavily used Application Servers, or Citrix Servers--since hundreds of userIDs can 'launch' applications, the results of CCMRUA on those types of machines often won't process (the MIF file will be bigger than 50mb) and isn't that useful anyway.  So go check, in your Custom Client Agent Settings, which collection you are targeting to enable 'ccm recently used apps'.  Once you know that, then continue.

1) first, determine with SQL query how big of an issue it might be; maybe it was only a couple of boxes; and you can address them manually. Depending upon the count returned, it'll be up to you if you want to pursue this as a Configuration Item, or manually address.

   Declare @CollID as nvarchar(8) = (Select collectionid from v_collection c where c.name = 'The Collection Name You figured out has CCMRUA as a HINV rule')
   select count(ws.resourceid) [Count]
   from v_gs_Workstations_Status ws
   where ws.LastHWScan is not null
   and ws.resourceid not in (select resourceid from v_gs_ccm_recently_used_apps)
   and ws.resourceid in (select resourceid from v_fullcollectionmembership_valid fcm where fcm.collectionid=@CollID)

2) Create the Collection Query, to target.

   - Create a new Collection, using the "limit to collection" as the collection you use for targeting when CCM Recently Used Apps information should be reported via Hardware Inventory. (the one you figured out above)

   - The collection query rule should have two conditions... where:
      SMS_G_System_WORKSTATION_STATUS.LastHardwareScan is not null
      and
      SMS_R_SYSTEM.ResourceId not in (Select ResourceId from SMS_G_System_CCM_RECENTLY_USED_APPS)

3) If the count of the SQL query, and the count of the Collection query are the same (or close enough); then you can continue to creating the ConfigItem, and deploying the Baseline to remediate the issue.

4) Create the Configuration Item, where the Detection and Remediation Logic are at the end of this blog post.  Both are Powershell scripts. for "what means compliant", it will be a String, equals "Compliant". Make sure you check the box about Remediate if non-compliant.

5) After you create the Configuration Item, create a Baseline, add the CI to the baseline, and deploy the baseline, with remediation, to the collection you created above. (you may want to do a pilot, to a subset of 2 or 3 specific boxes, just to be sure it will all work as you expect it to work)

6) That's it... then it's just a waiting game.  You are waiting for the Baseline to run, remediate the issue by doing the rundll routine, restart ccmexec.  Once that is done, in a minute or two mtrmgr.log will start to begin recording information into the root\cimv2\ccm_recentlyusedapps WMI location.  Once there is information there, then at the next hardware inventory, presuming this client is asked via hinv policy to report that information, it will have something to report.  So how long it takes completely depends upon YOUR schedules, that you defined.  How frequently the Baseline evaluates, and how frequently your clients do the scheduled HINV action.

PS: you might be tempted to "let me just add a line to the remediation script, to trigger a hinv right at the end".  I wouldn't bother.  It takes a few minutes for the client, after the ccmexec restart, to populate WMI.  It'll all shake out quickly enough.

######### DETECTION Powershell Script for the CI #####################
<#
.SYNOPSIS
   This Script is for Detection of a known condition for the inability of CM Client to initialize the StartPrepDriver
.DESCRIPTION
   This script finds the CM mgrmgr.log file, and reads it for a known good, or known error, condition.
   "what means good" =  mtrmgr.log contains lines like this
        PREP driver successfully initialized 
        or
        Termination event received for process
   "what means bad" = mtrmgr.log contains lines like this
        StartPrepDriver - OpenService Failed with error
.NOTES
   Steps are to
    1) read the regkey for CM Client to find the correct log file location
    2) Look for good or Bad entries in the file
    3) Exit with 'Compliant' or 'Non-Compliant' depending upon the results
.VERSION
    1.0 Sherry Kissinger  2017-03-30
#>
$ErrorActionPreference = 'SilentlyContinue'
#Get the LogDirectory for CM Client
$CMLogDir = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\CCM\Logging\@Global" -Name LogDirectory).LogDirectory
#Define the LogFile to Read
$CMLogFile = $CMLogDir + '\mtrmgr.log'
#Read the Log file for the Error Phrase
$GotErrors = (Get-Content -Path $CMLogFile | where-object {$_ -like '*StartPrepDriver - OpenService Failed with error*'})
#Read the Log File for a known good condition phrases
$GotGoodEntry = (Get-Content -Path $CMLogFile | where-object {($_ -like '*PREP driver successfully initialized*') -or ($_ -like '*Termination event received for process*')})
if ($GotGoodEntry) {
  write-host 'Compliant'
  }
else {
  if ($GotErrors) {
     write-host 'Non-Compliant'
  }
}

############## REMEDIATION Powershell Script for the CI  ##########################
<#
.SYNOPSIS
   This Script is for Detection and Remediation of a known condition for the inability of CM Client to initialize the StartPrepDriver
.DESCRIPTION
   This script finds the CM mgrmgr.log file, and reads it for a known good, or known error, condition.
   "what means good" =  mtrmgr.log contains lines like this
        PREP driver successfully initialized 
        or
        Termination event received for process
   "what means bad" = mtrmgr.log contains lines like this
        StartPrepDriver - OpenService Failed with error
.NOTES
   Steps are to
    1) read the regkey for CM Client to find the correct log file location
    2) Look for good or Bad entries in the file
    3) Exit with 'Compliant' or if 'Non-Compliant', to run the fix
       3a) the fix is two steps
            RUNDLL32.EXE SETUPAPI.DLL,InstallHinfSection DefaultInstall 128 C:\WINDOWS\CCM\prepdrv.inf
            Restart-Service ccmexec
.VERSION
    1.0 Sherry Kissinger  2017-03-30
#>
$ErrorActionPreference = 'SilentlyContinue'
#Get the LogDirectory for CM Client
$CMLogDir = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\CCM\Logging\@Global" -Name LogDirectory).LogDirectory
#Define the LogFile to Read
$CMLogFile = $CMLogDir + '\mtrmgr.log'
#Read the Log file for the Error Phrase
$GotErrors = (Get-Content -Path $CMLogFile | where-object {$_ -like '*StartPrepDriver - OpenService Failed with error*'})
#Read the Log File for a known good condition phrases
$GotGoodEntry = (Get-Content -Path $CMLogFile | where-object {($_ -like '*PREP driver successfully initialized*') -or ($_ -like '*Termination event received for process*')})
if ($GotGoodEntry) {
  write-host 'Compliant'
  }
else {
if ($GotErrors) {
 Try { Set-ExecutionPolicy -ExecutionPolicy 'Bypass' -Scope 'Process' -Force -ErrorAction 'Stop'}
 Catch {}
 $CMClientDIR = (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\SMS\Client\Configuration\Client Properties" -Name 'Local SMS Path').'Local SMS Path'
 $ExePath = $env:windir + '\system32\RUNDLL32.EXE'
 $CLine = ' SETUPAPI.DLL,InstallHinfSection DefaultInstall 128 ' + $CMClientDIR + 'prepdrv.inf'
 #Parse the Parameters
 $Prms = $Cline.Split(" ")
 #Execute the fix with parameters
 & "$Exepath" $Prms
 #Restart ccmexec service
 #CCMExec should be restarted; If you'd rather wait for a natural client reboot, comment out this line.
 #Note that this CI will continue to attempt to remediate until a ccmexec restart or reboot
 restart-service ccmexec
  }
}

 

 

Using Package Status MIF Files in a Task Sequence

$
0
0

Recently we internally had a need for technical people, but not necessarily people extremely versed in reading Task Sequence log files, to be able to tell via a report only why some step in a Task Sequence failed to trigger.

Pre-requisites and lessons learned during testing:

  1. Package/Program(s) defined with the source files containing 1 file:
     --> CreateMIF.ps1 <--
  2. The mif file has some specific structural requirements.  All Fields have to have a value, a returned value of “” (nothing) is not acceptable and won’t be picked up and forwarded.  So hard coding “ENU” for language and “NIL” for Serial Number is done in-script. (You can change the language if you like; but they have to match; in the script and in the Package Language)
  3. In order for CM client to match the .mif file correctly, several elements need to “match”; the filename, the Manufacturer, the PackageName, the Version, and ENU.
  4. In order for CM client to ‘find’ the mif file to forward to the MP, the mif file needs to be in the %windir% folder.

The remainder of this document is illustrating it’s use using a simple example:  Where a pre-requisite check for “is there enough hard drive space”, failed.  This is useful in reports for a verbose status description to help people via reporting only (without reading a long local log file on a client) determine why a step failed.

The steps of the script are essentially this:

  1. Grab the 6 required parameters

  2. Create the MIF in %windir%

Package Properties, note the values for 1, 2, 3, 4. NOTE that the script itself hard codes the value for “language” as ENU—so that has to be ENU on the General Tab here, item #4.

For Status MIF Matching on the Package, note values 1, 2, 3, and 5

In the program Command Line, note the values for 1, 2, 3, and 5; how they have to match the 1, 2, 3 in Package General Tab, and Reporting Tab.

Here’s a sample Task Sequence, using that package.

 

If it’s working, you’ll see this in execmgr.log on a client:

 

 

Using this additional SQL line in some specific reports, you’ll be able to see the “Description”, whatever it may be:
, StatusMifDescription= (select sstring.InsStrValue3 from vStatusMessagesWithStrings sstring where sstring.messageid in (10007,10009) and sstring.recordid=stat.recordid)
in "__History of a Task Sequence Deployment on a Computer"

 

For the curious... why did I use such an odd number for "enough free disk"; because that's about what was free on the test box.  so I could easily test for that, over and over again.

 

If for whatever reason you can't get the attached .zip file, below is the script:

<#
.SYNOPSIS
 This script creates a System Center Configuration Manager compliant status.mif file
.DESCRIPTION
 This script creates a specifically formated text file ending in '.mif' in the $windir folder.
.PARAMETER MIFFileName
 The Name to give the .mif filename, excluding the .mif extension.  This must match the filename in ConfigMgr package status mif matching.
.PARAMETER Company
 The Company or Manufacturer must match the Manufacturer as defined in the Package Properties in ConfigMgr
.PARAMETER Package
 This must match the Package name as defined in the Package Properties in ConfigMgr
.PARAMETER Version
 This must match the version as defined in the Package Properties in ConfigMgr
.PARAMETER Description
 This can be any sentance or phrase, up to 254 characters
.PARAMETER Status
 The only acceptable values are SUCCESS or FAILURE
.EXAMPLE
 Create-MIF.ps1 -MIFFileName ABC12345 -Company 'Acme Corporation' -Package 'Widgets' -Version '3.0' -Description 'Requirement of enough disk space not met' -Status 'Failure'
.EXAMPLE
 Create-MIF.ps1 -MIFFileName ABC12345 -Company 'Acme Corporation' -Package 'Widgets' -Version '3.0' -Description 'Requirement enough disk space met' -Status 'Success'
.NOTES
 On Package Properties in ConfigMgr, the Language of ENU must exist
 The resulting MIF file created needs be in the %windir% folder for ConfigMgr to utilize it.
.VERSION
 1.0 Sherry Kissinger 03-27-2017
#>
[CMDletBinding()]
Param (
 [Parameter(Mandatory=$true)]
 [string]$MIFFileName,
 [Parameter(Mandatory=$true)]
 [string]$Company,
 [Parameter(Mandatory=$true)]
 [string]$Package,
 [Parameter(Mandatory=$true)]
 [string]$Version,
 [Parameter(Mandatory=$true)]
 [string]$Description,
 [Parameter(Mandatory=$true)]
 [ValidateSet('Failed','Success')]
 [string]$Status  
)
$Locale = "ENU"
$SerNum = "NIL"
$FileName = $Env:WinDir+'\'+$MIFFileName + '.mif'
$DoubleQuote = '"'
"START COMPONENT" | Set-Content $FileName
"NAME = " + $DoubleQuote + "WORKSTATION" + $DoubleQuote | Add-Content $FileName
"  START GROUP" | Add-Content $FileName
"    NAME = " + $DoubleQuote + "ComponentID" + $DoubleQuote | Add-Content $FileName
"    ID = 1"  | Add-Content $FileName
"    CLASS = " + $DoubleQuote + "DMTF|ComponentID|1.0" + $DoubleQuote | Add-Content $FileName
"    START ATTRIBUTE" | Add-Content $FileName
"      NAME = " +$DoubleQuote + "Manufacturer" + $DoubleQuote | Add-Content $FileName
"      ID = 1" | Add-Content $FileName
"      ACCESS = READ-ONLY" | Add-Content $FileName
"      STORAGE = SPECIFIC" | Add-Content $FileName
"      TYPE = STRING(64)" | Add-Content $FileName
"      VALUE = " + $DoubleQuote + $Company + $DoubleQuote | Add-Content $FileName
"    END ATTRIBUTE" | Add-Content $FileName
"    START ATTRIBUTE" | Add-Content $FileName
"      NAME = " + $DoubleQuote + "Product" + $DoubleQuote | Add-Content $FileName
"      ID = 2" | Add-Content $FileName
"      ACCESS = READ-ONLY" | Add-Content $FileName
"      STORAGE = SPECIFIC" | Add-Content $FileName
"      TYPE = STRING(64)" | Add-Content $FileName
"      VALUE = " + $DoubleQuote + $Package + $DoubleQuote | Add-Content $FileName
"    END ATTRIBUTE" | Add-Content $FileName
"    START ATTRIBUTE" | Add-Content $FileName
"      NAME = " + $DoubleQuote + "Version" + $DoubleQuote  | Add-Content $FileName
"      ID = 3"  | Add-Content $FileName
"      ACCESS = READ-ONLY"  | Add-Content $FileName
"      STORAGE = SPECIFIC" | Add-Content $FileName
"      TYPE = STRING(64)" | Add-Content $FileName
"      VALUE = " + $DoubleQuote + $Version + $DoubleQuote | Add-Content $FileName
"    END ATTRIBUTE" | Add-Content $FileName
"    START ATTRIBUTE" | Add-Content $FileName
"      NAME = " + $DoubleQuote + "Locale" + $DoubleQuote  | Add-Content $FileName
"      ID = 4" | Add-Content $FileName
"      ACCESS = READ-ONLY" | Add-Content $FileName
"      STORAGE = SPECIFIC" | Add-Content $FileName
"      TYPE = STRING(16)" | Add-Content $FileName
"      VALUE = " + $DoubleQuote + $Locale + $DoubleQuote  | Add-Content $FileName
"    END ATTRIBUTE" | Add-Content $FileName
"    START ATTRIBUTE" | Add-Content $FileName
"      NAME = " + $DoubleQuote + "Serial Number" + $DoubleQuote  | Add-Content $FileName
"      ID = 5"  | Add-Content $FileName
"      ACCESS = READ-ONLY" | Add-Content $FileName
"      STORAGE = SPECIFIC" | Add-Content $FileName
"      TYPE = STRING(64)" | Add-Content $FileName
"      VALUE = " + $DoubleQuote + $SerNum + $DoubleQuote  | Add-Content $FileName
"    END ATTRIBUTE" | Add-Content $FileName
"    START ATTRIBUTE" | Add-Content $FileName
"      NAME = " + $DoubleQuote + "Installation" + $DoubleQuote | Add-Content $FileName
"      ID = 6" | Add-Content $FileName
"      ACCESS = READ-ONLY" | Add-Content $FileName
"      STORAGE = SPECIFIC" | Add-Content $FileName
"      TYPE = STRING(64)" | Add-Content $FileName
"      VALUE = " + $DoubleQuote + "DateTime" +$DoubleQuote | Add-Content $FileName
"    END ATTRIBUTE" | Add-Content $FileName
"  END GROUP" | Add-Content $FileName
"  START GROUP" | Add-Content $FileName
"    NAME = " + $DoubleQuote + "InstallStatus" + $DoubleQuote  | Add-Content $FileName
"    ID = 2" | Add-Content $FileName
"    CLASS = " + $DoubleQuote + "MICROSOFT|JOBSTATUS|1.0" + $DoubleQuote | Add-Content $FileName
"    START ATTRIBUTE" | Add-Content $FileName
"      NAME = " + $DoubleQuote + "Status" + $DoubleQuote | Add-Content $FileName
"      ID = 1"  | Add-Content $FileName
"      ACCESS = READ-ONLY" | Add-Content $FileName
"      STORAGE = SPECIFIC" | Add-Content $FileName
"      TYPE = STRING(32)" | Add-Content $FileName
"      VALUE = " + $DoubleQuote + $Status + $DoubleQuote | Add-Content $FileName
"    END ATTRIBUTE" | Add-Content $FileName
"    START ATTRIBUTE" | Add-Content $FileName
"      NAME = " + $DoubleQuote + "Description" + $DoubleQuote | Add-Content $FileName
"      ID = 2" | Add-Content $FileName
"      ACCESS = READ-ONLY" | Add-Content $FileName
"      STORAGE = SPECIFIC" | Add-Content $FileName
"      TYPE = STRING(128)" | Add-Content $FileName
"      VALUE = " + $DoubleQuote + $Description + $DoubleQuote | Add-Content $FileName
"    END ATTRIBUTE" | Add-Content $FileName
"  END GROUP" | Add-Content $FileName
"END COMPONENT" | Add-Content $FileName
Exit 0
 

 

Configmgr Reports Leveraging SrsResources.dll display #Error instead of localized error descriptions

$
0
0

Issue:  Leveraging SrsResources.dll using ConfigMgr Reporting Services Reports used to work... but after an upgrade or reconfiguration any reports using the expression "=SrsResources.Localization.GetErrorMessage(Fields!ErrorCode.Value, User!Language) "  in the report just says #Error

Resolution:

I'll give the quick resolution here, and the long explanation later.

  1. Get the absolute latest version of SrsResources.dll you have, by looking at any CM Administration Console installation, in the \bin folder.
  2. On the Server which has your ConfigMgr Reporting Services Role, on the same drive where you have that role, make a directory (call it whatever you like, but for this example, I'm calling it CMSrsResources, and for me, the drive was S:.  Copy that latest SrsResources.dll to S:\CMSrsResources folder.
  3. On the Server which has your ConfigMgr Reporting Services role, you will have had to install SQL Reporting Services.  Find that installed location, it might be on C:, D:, or elsewhere.  The folder will likely be "something like" ....\MSRS13.MSSQLServer\Reporting Services\ReportServer.  In that location will be a rssrvpolicy.config file.  Edit rssrvpolicy.config in notepad, and look for the reference to SrsResources.dll.  It is most likely pointing to ...\MSRS13.MSSQLServer\Reporting Services\ReportServer\bin\SrsResources.dll.  CHANGE that to point instead to what you did in Step 2.  In my case, it would be S:\CMSrsResources\SrsResources.dll.  Save the config file.  (if it won't LET you save the config file, go to Services, and stop the SQL Reporting Services 'service', then save it.)
  4. Restart the service for SQL Reporting Services, or Restart the Server.

Done.

The long Explanation...

We have multiple custom reports, especially for Application Deployments, where knowing what an errorcode number means in a localized language (in our case, usually English) is very handy, instead of looking at that information in the console.  SQL reports are preferred in many instances.  In order to get that localization, according to multiple sources, the way to do that using ConfigMgr is 3 steps:

  1. rssrvpolicy.config for your SQL Reporting Services needs to have the SCCM Assembly referenced, pointing to the location of the SrsResources.dll file.
  2. that SrsResources.dll file has to exist in that location identified in the .config file.
  3. for any individual Report for ConfigMgr, for the report properties, on the 'References' tab, add the SrsResources assembly. Inside that report, presuming an error code is one of the values of your dataset, you can use the expression =SrsResources.Localization.GetErrorMessage(Fields!ErrorCode.Value, User!Language to get that information displayed in legible english (if you are english speaking, french if you're french, etc. etc.)

I noticed after CM 1610, and then again after CM 1702, apparently what is done "for me" is either permissions are reset, or something else fun is happening--maybe it's only when you are using SQL 2016, I don't know (all my labs and production are SQL 2016 latest).  But the .config file, if it's pointing to the Reporting Services\ReportServer\Bin location... It just won't read it and use it.  What the report displays instead of a nice handy english-y message is just #Error .  If I instead copy the .dll elsewhere, and edit the .config file to say "go find it over here" -- it uses it just fine.

Here's hoping this might help others if they like leveraging the SrsResources.dll within ConfigMgr reports, and they are doing everything by the book... and yet it still doesn't work.  You might just need to copy the .dll elsewhere and edit the config file.

Viewing all 45 articles
Browse latest View live