<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Mihai Sarbulescu's System Center Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/mihai/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/mihai/feed.xml</link>
    <description>let&amp;#039;s play with System Center</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:47:39 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Network Discovery not working in SCOM due to DLL corruption (debugging DLL loader component - LDR)</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/network-discovery-not-working-in-scom-due-to-dll-corruption-debugging-dll-loader-component-ldr</link>
      <pubDate>Thu, 06 Jul 2017 01:20:35 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/?p=1005</guid>
      <description><![CDATA[So, wow, this was nice! ... a super one-off scenario related to SCOM. This is very interesting...]]></description>
      <content:encoded><![CDATA[So, wow, this was nice! ... a super one-off scenario related to SCOM. This is very interesting though from a point of view of debugging and can theoretically happen in any application, so we are going to have a look at how to debug (and automate debugging) of the DLL Loader component (<strong>LDR</strong>) from <strong>ntdll.dll</strong>.

Let's start with the actual issue first :D

SCOM Network Discovery component is not working and the error we can see being logged in the <em><strong>Operations Manager</strong> </em>event log on the Management Server which is configured to run the Network Discovery rule, is <strong>Error</strong> event ID <span style="color: #ff0000"><strong>157</strong></span>:
<pre class="trace"><span style="font-size: small">Creation of module with CLSID "{<span style="color: #0000ff"><strong>6620A03E-9E85-4BEA-947C-D508CDB540FE</strong></span>}" failed with error "<strong><span style="color: #ff0000">%1 is not a valid Win32 application</span>.</strong>" in rule "discovery<em>&lt;SOME_NUMBER&gt;</em>.<em>&lt;SOME_GUID&gt;</em>" running for instance "<em>&lt;SOME_NAME&gt;</em>" with id:"{<em>&lt;SOME_GUID&gt;</em>}" in management group "<em>&lt;SOME_MG_NAME&gt;</em>".</span></pre>
Now the error "<span style="color: #ff0000"><strong>not a valid Win32 application</strong></span>" means that we are trying to load an EXE or DLL file and it has one of 2 issues:
<ol>
 	<li>we either are trying to load a 32bit binary file from a 64bit process (or the other way around - very uncommon ... but not impossible)</li>
 	<li>or there is something directly wrong with the binary file contents (some corruption at the file structure level / header): <a target="_blank" href="https://en.wikipedia.org/wiki/Portable_Executable" rel="noopener noreferrer">https://en.wikipedia.org/wiki/Portable_Executable</a></li>
</ol>
But what file (most probably DLL) is this?! We have the <strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms691424(v=vs.85).aspx" rel="noopener noreferrer">CLSID</a></strong> in the error which is: <span style="color: #0000ff"><strong>6620A03E-9E85-4BEA-947C-D508CDB540FE</strong></span>

So how do we figure out which DLL it is? By searching in the registry (on a SCOM Management Server) by that <strong>CLSID</strong> and somewhere under <strong>HKEY_CLASSES_ROOT\CLSID\</strong>, we should find this GUID - and after a search, we do and under: <strong>HKEY_CLASSES_ROOT\CLSID\{<span style="color: #0000ff">6620A03E-9E85-4bea-947C-D508CDB540FE</span>}\InprocServer32</strong>, we find the value called <strong>(Default)</strong> which contains the full path to the DLL: <strong>C:\Program Files\Microsoft System Center 2012 R2\Operations Manager\Server\<span style="color: #ff6600">NetworkDiscoveryModules.dll</span></strong>

&nbsp;

Pah! Super simple, right? It looks like the <strong><span style="color: #ff6600">NetworkDiscoveryModules.dll</span></strong> is somehow corrupted and we should just replace it with a working one from a SCOM Management Server with the exact same SCOM version and Update Rollup installed - right?!

Well, we did that and it did not work ... so whaaat is going on here?!

&nbsp;

Well, this clearly is not a "SCOM" issue, but some file/OS related issue that can happen with any software - but, because I am a curious man ...

<a href="https://msdnshared.blob.core.windows.net/media/2017/06/alrightythen.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2017/06/alrightythen-300x228.jpg" alt="" width="300" height="228" class="size-medium wp-image-1006 aligncenter" /></a>

&nbsp;

First things first - let's totally separate our problem from SCOM and let's manually try to reproduce the problem by just loading the DLL directly - we don't need to complicate ourselves with writing native code, we can just do this in PowerShell directly - like <strong><a target="_blank" href="https://blogs.technet.microsoft.com/heyscriptingguy/2013/06/25/use-powershell-to-interact-with-the-windows-api-part-1/" rel="noopener noreferrer">this</a></strong>:
<pre class="trace"><span style="font-size: small">Add-Type @"
using System;
using System.Runtime.InteropServices;
public static class NativeMethods {
   [DllImport(@"$($env:ProgramFiles)\Microsoft System Center 2012 R2\Operations Manager\Server\NetworkDiscoveryModules.dll")]
   public static extern void DllCanUnloadNow();
}
"@
[NativeMethods]::DllCanUnloadNow()</span></pre>
Extra info for the other curious people out there about this script:
<ul>
 	<li>it will create a C# file which will get compiled in a temporary directory that will do the actual native (C/C++) DLL loading/import</li>
 	<li>after this, we will call a standard DLL function (usually included in every DLL - verified that we have it in <strong><span style="color: #ff6600">NetworkDiscoveryModules.dll</span></strong> because I can look at the code :p - but you can usually rely on the fact that almost all DLLs have this) - <strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms690368(v=vs.85).aspx" rel="noopener noreferrer">DllCanUnloadNow()</a></strong></li>
 	<li>this function - <strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms690368(v=vs.85).aspx" rel="noopener noreferrer">DllCanUnloadNow()</a></strong> - will not return anything from this PowerShell script on a computer where there is no issue with the DLL - however, it will return an error if there is something wrong with it - just like this one below which we got when running the script on the affected server:</li>
</ul>
<a href="https://msdnshared.blob.core.windows.net/media/2017/06/ps_error1.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2017/06/ps_error1-1024x77.jpg" alt="" width="1024" height="77" class="size-large wp-image-1016 aligncenter" /></a>

So the error we are getting is actually the same (only more descriptive): <span style="color: #ff0000"><strong>An attempt was made to load a program with an incorrect format.</strong></span>

&nbsp;

Ok cool! So now we can reproduce the issue totally outside of SCOM, by just trying to load that DLL and calling a function from it (because only when we make an actual call will the DLL be truly loaded for code execution).

So, now we can do a live debug by attaching to the <strong>PowerShell.exe</strong> process which we will use to execute that script: <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/" rel="noopener noreferrer">https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/</a>

Everything I will show next in the debugger, will be using <strong>Public Symbols</strong>, so everyone can follow the steps (don't need any internal private symbols): <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/microsoft-public-symbols" rel="noopener noreferrer">https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/microsoft-public-symbols</a>

The Windows <strong>LDR</strong> works like this:
<ol>
 	<li>we want to load DLL whatever.dll</li>
 	<li>we go verify if the binary file has the correct bitness and if it's not corrupt in any way</li>
 	<li>if all goes well, we check the import section and for each DLL which it is dependent on, we do the exact same thing one by one - steps 1 to 3 for each of them</li>
 	<li>if any of the DLLs in the import section cannot be correctly loaded (not correct bitness, corrupt in some way, etc.) we will fail and throw the error describing why the DLL cannot be loaded - however, we throw the error for the initial DLL we were trying to load, we don't specify if there actually was a failure in the loading of one of the dependent DLLs</li>
</ol>
So we need to track down which dependent DLL has the actual corruption ...

Where do we break to check what is wrong? Well, we have these 2 nice function calls where we will break and check what is going on:
<ol>
 	<li><strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx" rel="noopener noreferrer">kernelbase!LoadLibraryExW</a></strong> which is used to load DLLs by Windows OS (<strong>Ex</strong> comes from "Extended" which means being able to pass in more "options" - parameters and <strong>W</strong> comes from the fact that the UNICODE string version of it is being used) <strong>=&gt; we are just starting here in order to continue with  the investigation with other breakpoints only when we reach the point where we are trying to load the DLL we are interested in troubleshooting (in this case <span style="color: #ff6600">NetworkDiscoveryModules.dll</span>)</strong></li>
 	<li><strong>ntdll!LdrpFindOrMapDll</strong> (<em>not documented on MSDN, should not directly be used</em>) which will get called by the DLL loader component (<strong>LDR</strong>) to try to find the DLL in different places, verify binary file structures/header, load all the DLL that it is dependent on (verifying consistency of each as well) and in the end load the actual DLL we call in order to be able to execute from it <strong>=&gt; this will be important because this is where we can get the DLL file name that we are currently trying to load</strong></li>
 	<li><strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff566428(v=vs.85).aspx" rel="noopener noreferrer">ntdll!ZwCreateSection</a></strong> which goes into Kernel and does the actual file read from disk and checks the required information (is it execution code, does it have a valid "MZ" start, is the header ok?, does it have the correct bitness?, etc.) <strong>=&gt; this is the actual function call we are interested in the end, because this is the one that will return the actual error in case that we have an issue loading the binary file to execute from it</strong></li>
</ol>
Let's set the first breakpoint and go in WinDbg:
<pre class="trace"><span style="font-size: small"><strong>0:000&gt; bp kernelbase!LoadLibraryExW</strong>

<strong>0:000&gt; g</strong>
Breakpoint 0 hit
kernelbase!LoadLibraryExW:
00007ffe`36b48d10 48895c2410 mov qword ptr [rsp+10h],rbx ss:0000000c`301d4b38=0000000c301d91a8</span></pre>
So, sure enough, we will break on the first/next execution of <strong>kernelbase!LoadLibraryExW</strong> and we can check what DLL is currently being loaded.

Just as an "FYI" we can/will also have a look at the stack because we are curious people:
<pre class="trace"><span style="font-size: small"><strong>0:001&gt; k</strong>
Child-SP RetAddr Call Site
0000000c`301d4b28 00007ffe`310ae4b4 <span style="color: #993300"><strong>kernelbase!LoadLibraryExW</strong></span>
0000000c`301d4b30 00007ffe`310ae421 clr!CLRLoadLibraryExWorker+0x54
0000000c`301d4b80 00007ffe`31098aff clr!CLRLoadLibraryEx+0x51
0000000c`301d4bd0 00007ffe`31098a28 clr!LoadedImageLayout::LoadedImageLayout+0xca
0000000c`301d4e90 00007ffe`313f6a84 clr!PEImageLayout::Load+0x3d
0000000c`301d4ed0 00007ffe`313f69de clr!PEImage::GetLayoutInternal+0x361930
0000000c`301d4f20 00007ffe`3107ee8f clr!PEImage::GetLayout+0x36195e
0000000c`301d4fa0 00007ffe`3107ed53 clr!RuntimeOpenImageInternal+0xcf
0000000c`301d5080 00007ffe`3107ec7b clr!GetAssemblyMDInternalImportEx+0xcd
0000000c`301d5100 00007ffe`310d3cc9 clr!CreateMetaDataImport+0x1b
0000000c`301d5140 00007ffe`310d3c1d clr!BindResult::Init+0x69
0000000c`301d51b0 00007ffe`3118867b clr!BindResult::CreateFromPath+0xc9
0000000c`301d5220 00007ffe`31188891 clr!NATIVE_BINDER_SPACE::VerifyNativeCandidate+0x55f
0000000c`301d58b0 00007ffe`31086b40 clr!NATIVE_BINDER_SPACE::CreateVerifiedNICandidate+0x10a
0000000c`301d5bc0 00007ffe`31085f39 clr!NATIVE_BINDER_SPACE::BindToNativeDependency+0x2ac
0000000c`301d5de0 00007ffe`31085803 clr!BindToNativeAssembly+0xed
0000000c`301d5f00 00007ffe`3108799f clr!BindToNativeImage+0x1bb
0000000c`301d6230 00007ffe`31082a6b clr!CAsmDownloadMgr::RecordInfoAndProbeNativeImage+0x106
0000000c`301d62a0 00007ffe`3108303b clr!CAsmDownloadMgr::PreDownloadCheck+0x518
0000000c`301d6ae0 00007ffe`31082e45 clr!CAssemblyDownload::PreDownload+0xb7
0000000c`301d6b80 00007ffe`3108251a clr!CAssemblyName::BindToObject+0x419
0000000c`301d6cd0 00007ffe`310822c2 clr!FusionBind::RemoteLoad+0x1aa
0000000c`301d6e10 00007ffe`31082047 clr!AssemblySpec::LoadAssembly+0x19a
0000000c`301d6f30 00007ffe`31081cf5 clr!AssemblySpec::FindAssemblyFile+0x113
0000000c`301d76d0 00007ffe`3108a4ae clr!AppDomain::BindAssemblySpec+0xef7
0000000c`301d8950 00007ffe`310ab18b clr!AssemblySpec::LoadDomainAssembly+0x1ec
0000000c`301d8f00 00007ffe`3118c9e8 clr!AssemblySpec::LoadAssembly+0x1b
0000000c`301d8f40 00007ffe`2f6ebde2 clr!AssemblyNative::Load+0x304
0000000c`301d92b0 00007ffe`304c4326 mscorlib_ni!System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Reflection.RuntimeAssembly, System.Threading.StackCrawlMark ByRef, IntPtr, Boolean, Boolean, Boolean)+0xd2
0000000c`301d9360 00007ffe`31209f51 mscorlib_ni!System.Reflection.RuntimeAssembly.LoadWithPartialNameInternal(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Threading.StackCrawlMark ByRef)+0xd66ad6
0000000c`301d93e0 00007ffe`31209e4f clr!ExceptionTracker::CallHandler+0xc5
0000000c`301d9480 00007ffe`312081c7 clr!ExceptionTracker::CallCatchHandler+0x7f
0000000c`301d9510 00007ffe`396c347d clr!ProcessCLRException+0x2e6
0000000c`301d95f0 00007ffe`39685405 ntdll!RtlpExecuteHandlerForUnwind+0xd
0000000c`301d9620 00007ffe`31208260 ntdll!RtlUnwindEx+0x385
0000000c`301d9d00 00007ffe`3120821c clr!ClrUnwindEx+0x40
0000000c`301da220 00007ffe`396c33fd clr!ProcessCLRException+0x2b2
0000000c`301da300 00007ffe`39684847 ntdll!RtlpExecuteHandlerForException+0xd
0000000c`301da330 00007ffe`39683a6d ntdll!RtlDispatchException+0x197
0000000c`301daa00 00007ffe`36b495fc ntdll!RtlRaiseException+0x18d
0000000c`301db1c0 00007ffe`31209864 kernelbase!RaiseException+0x68
0000000c`301db2a0 00007ffe`314bb7ef clr!RaiseTheExceptionInternalOnly+0x2fe
0000000c`301db3a0 00007ffe`3118cb37 clr!UnwindAndContinueRethrowHelperAfterCatch+0x80
0000000c`301db3f0 00007ffe`2f75d99e clr!AssemblyNative::Load+0x453
0000000c`301db760 00007ffe`2ff13666 mscorlib_ni!System.Reflection.RuntimeAssembly.LoadWithPartialNameInternal(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Threading.StackCrawlMark ByRef)+0x14e
0000000c`301db890 00007ffe`1933970f mscorlib_ni!System.Reflection.Assembly.LoadWithPartialName(System.String)+0x46
0000000c`301db8e0 00007ffe`193394e1 system_management_automation_ni!System.Management.Automation.ExecutionContext.LoadAssembly(System.String, System.String, System.Exception ByRef)+0x15f
0000000c`301db9a0 00007ffe`193211f2 system_management_automation_ni!System.Management.Automation.ExecutionContext.AddAssembly(System.String, System.String, System.Exception ByRef)+0x21
0000000c`301db9f0 00007ffe`19316887 system_management_automation_ni!Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadBinaryModule(System.Management.Automation.PSModuleInfo, Boolean, System.String, System.String, System.Reflection.Assembly, System.String, System.Management.Automation.SessionState, ImportModuleOptions, ManifestProcessingFlags, System.String, Boolean, Boolean, Boolean ByRef, System.String, Boolean)+0x452
0000000c`301dbbf0 00007ffe`1931b82b system_management_automation_ni!Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadModuleNamedInManifest(System.Management.Automation.PSModuleInfo, Microsoft.PowerShell.Commands.ModuleSpecification, System.String, Boolean, System.String, System.Management.Automation.SessionState, ImportModuleOptions, ManifestProcessingFlags, Boolean, Boolean, System.Object, Boolean ByRef, System.String)+0x977
0000000c`301dbe20 00007ffe`19316ab5 system_management_automation_ni!Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadModuleManifest(System.String, System.Management.Automation.ExternalScriptInfo, System.Collections.Hashtable, System.Collections.Hashtable, ManifestProcessingFlags, System.Version, System.Version, ImportModuleOptions ByRef, Boolean ByRef)+0x4d0b
0000000c`301dc9d0 00007ffe`1931fa1b system_management_automation_ni!Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadModuleManifest(System.Management.Automation.ExternalScriptInfo, ManifestProcessingFlags, System.Version, System.Version, ImportModuleOptions ByRef)+0xd5
0000000c`301dca70 00007ffe`1932386c system_management_automation_ni!Microsoft.PowerShell.Commands.ModuleCmdletBase.LoadModule(System.Management.Automation.PSModuleInfo, System.String, System.String, System.String, System.Management.Automation.SessionState, System.Object, ImportModuleOptions ByRef, ManifestProcessingFlags, Boolean ByRef, Boolean ByRef)+0xc4b
0000000c`301dcda0 00007ffe`193241d8 system_management_automation_ni!Microsoft.PowerShell.Commands.ImportModuleCommand.ImportModule_LocallyViaName(ImportModuleOptions, System.String)+0x4ac
0000000c`301dcef0 00007ffe`193dbb0e system_management_automation_ni!Microsoft.PowerShell.Commands.ImportModuleCommand.ProcessRecord()+0x198
0000000c`301dcfd0 00007ffe`19382b55 system_management_automation_ni!System.Management.Automation.CommandProcessor.ProcessRecord()+0x29e
0000000c`301dd080 00007ffe`1937953e system_management_automation_ni!System.Management.Automation.CommandProcessorBase.DoExecute()+0xe5
0000000c`301dd0f0 00007ffe`193666d0 system_management_automation_ni!System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(System.Object, System.Collections.Hashtable, Boolean)+0x17e
0000000c`301dd1e0 00007ffe`1936581f system_management_automation_ni!System.Management.Automation.Runspaces.LocalPipeline.InvokeHelper()+0x750
0000000c`301dd400 00007ffe`19365241 system_management_automation_ni!System.Management.Automation.Runspaces.LocalPipeline.InvokeThreadProc()+0x2af
0000000c`301dd550 00007ffe`193348d5 system_management_automation_ni!System.Management.Automation.Runspaces.LocalPipeline.StartPipelineExecution()+0x321
0000000c`301dd5d0 00007ffe`19363fe4 system_management_automation_ni!System.Management.Automation.Runspaces.PipelineBase.CoreInvoke(System.Collections.IEnumerable, Boolean)+0x305
0000000c`301dd650 00007ffe`193df48e system_management_automation_ni!System.Management.Automation.Runspaces.PipelineBase.Invoke(System.Collections.IEnumerable)+0x24
0000000c`301dd690 00007ffe`193deff0 system_management_automation_ni!System.Management.Automation.PowerShell+Worker.ConstructPipelineAndDoWork(System.Management.Automation.Runspaces.Runspace, Boolean)+0x2de
0000000c`301dd770 00007ffe`193d9fbe system_management_automation_ni!System.Management.Automation.PowerShell.CoreInvokeHelper[[System.__Canon, mscorlib],[System.__Canon, mscorlib]](System.Management.Automation.PSDataCollection`1&lt;System.__Canon&gt;, System.Management.Automation.PSDataCollection`1&lt;System.__Canon&gt;, System.Management.Automation.PSInvocationSettings)+0x350
0000000c`301dd820 00007ffe`193d9aca system_management_automation_ni!System.Management.Automation.PowerShell.CoreInvoke[[System.__Canon, mscorlib],[System.__Canon, mscorlib]](System.Management.Automation.PSDataCollection`1&lt;System.__Canon&gt;, System.Management.Automation.PSDataCollection`1&lt;System.__Canon&gt;, System.Management.Automation.PSInvocationSettings)+0x4de
0000000c`301dd9b0 00007ffe`193efca0 system_management_automation_ni!System.Management.Automation.PowerShell.CoreInvoke[[System.__Canon, mscorlib]](System.Collections.IEnumerable, System.Management.Automation.PSDataCollection`1&lt;System.__Canon&gt;, System.Management.Automation.PSInvocationSettings)+0x1ba
0000000c`301dda60 00007ffe`193ed6c2 system_management_automation_ni!System.Management.Automation.CommandDiscovery.AutoloadSpecifiedModule(System.String, System.Management.Automation.ExecutionContext, System.Management.Automation.SessionStateEntryVisibility, System.Exception ByRef)+0x2c0
0000000c`301ddb00 00007ffe`19376326 system_management_automation_ni!System.Management.Automation.CommandDiscovery.TryModuleAutoDiscovery(System.String, System.Management.Automation.ExecutionContext, System.String, System.Management.Automation.CommandOrigin, System.Management.Automation.SearchResolutionOptions, System.Management.Automation.CommandTypes, System.Exception ByRef)+0x312
0000000c`301ddc10 00007ffe`19375ed1 system_management_automation_ni!System.Management.Automation.CommandDiscovery.LookupCommandInfo(System.String, System.Management.Automation.CommandTypes, System.Management.Automation.SearchResolutionOptions, System.Management.Automation.CommandOrigin, System.Management.Automation.ExecutionContext)+0x3d6
0000000c`301ddcf0 00007ffe`193dd8ce system_management_automation_ni!System.Management.Automation.CommandDiscovery.LookupCommandProcessor(System.String, System.Management.Automation.CommandOrigin, System.Nullable`1&lt;Boolean&gt;)+0x31
0000000c`301ddd50 00007ffe`193dcfd1 system_management_automation_ni!System.Management.Automation.ExecutionContext.CreateCommand(System.String, Boolean)+0x6e
0000000c`301dddb0 00007ffe`19335255 system_management_automation_ni!System.Management.Automation.PipelineOps.AddCommand(System.Management.Automation.Internal.PipelineProcessor, System.Management.Automation.CommandParameterInternal[], System.Management.Automation.Language.CommandBaseAst, System.Management.Automation.CommandRedirection[], System.Management.Automation.ExecutionContext)+0x3f1
0000000c`301ddef0 00007ffe`1a0a036e system_management_automation_ni!System.Management.Automation.PipelineOps.InvokePipeline(System.Object, Boolean, System.Management.Automation.CommandParameterInternal[][], System.Management.Automation.Language.CommandBaseAst[], System.Management.Automation.CommandRedirection[][], System.Management.Automation.Language.FunctionContext)+0x135
0000000c`301ddfb0 00007ffe`1938591b system_management_automation_ni!System.Management.Automation.Interpreter.ActionCallInstruction`6[[System.__Canon, mscorlib],[System.Boolean, mscorlib],[System.__Canon, mscorlib],[System.__Canon, mscorlib],[System.__Canon, mscorlib],[System.__Canon, mscorlib]].Run(System.Management.Automation.Interpreter.InterpretedFrame)+0x19e
0000000c`301de050 00007ffe`1938591b system_management_automation_ni!System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(System.Management.Automation.Interpreter.InterpretedFrame)+0x16b
0000000c`301de160 00007ffe`1938575b system_management_automation_ni!System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(System.Management.Automation.Interpreter.InterpretedFrame)+0x16b
0000000c`301de270 00007ffe`193752af system_management_automation_ni!System.Management.Automation.Interpreter.Interpreter.Run(System.Management.Automation.Interpreter.InterpretedFrame)+0x7b
0000000c`301de2f0 00007ffe`19383925 system_management_automation_ni!System.Management.Automation.Interpreter.LightLambda.RunVoid1[[System.__Canon, mscorlib]](System.__Canon)+0x11f
0000000c`301de380 00007ffe`193832f8 system_management_automation_ni!System.Management.Automation.DlrScriptCommandProcessor.RunClause(System.Action`1&lt;System.Management.Automation.Language.FunctionContext&gt;, System.Object, System.Object)+0x405
0000000c`301de510 00007ffe`19382fce system_management_automation_ni!System.Management.Automation.DlrScriptCommandProcessor.Complete()+0x1a8
0000000c`301de5c0 00007ffe`19382d01 system_management_automation_ni!System.Management.Automation.CommandProcessorBase.DoComplete()+0x16e
0000000c`301de680 00007ffe`19379551 system_management_automation_ni!System.Management.Automation.Internal.PipelineProcessor.DoCompleteCore(System.Management.Automation.CommandProcessorBase)+0xb1
0000000c`301de720 00007ffe`193666d0 system_management_automation_ni!System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(System.Object, System.Collections.Hashtable, Boolean)+0x191
0000000c`301de810 00007ffe`1936581f system_management_automation_ni!System.Management.Automation.Runspaces.LocalPipeline.InvokeHelper()+0x750
0000000c`301dea30 00007ffe`192e7001 system_management_automation_ni!System.Management.Automation.Runspaces.LocalPipeline.InvokeThreadProc()+0x2af
0000000c`301deb80 00007ffe`2f6d2d45 system_management_automation_ni!System.Management.Automation.Runspaces.PipelineThread.WorkerProc()+0x31
0000000c`301debb0 00007ffe`2f6d2ab9 mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x285
0000000c`301ded10 00007ffe`2f6d2a97 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x9
0000000c`301ded40 00007ffe`2f6ea161 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x57
0000000c`301ded90 00007ffe`3103afb3 mscorlib_ni!System.Threading.ThreadHelper.ThreadStart()+0x51
0000000c`301dede0 00007ffe`3103ae9e clr!CallDescrWorkerInternal+0x83
0000000c`301dee20 00007ffe`3103b632 clr!CallDescrWorkerWithHandler+0x4a
0000000c`301dee60 00007ffe`31146bd9 clr!MethodDescCallSite::CallTargetWorker+0x251
0000000c`301df010 00007ffe`3103c8e1 clr!ThreadNative::KickOffThread_Worker+0x105
0000000c`301df270 00007ffe`3103c868 clr!ManagedThreadBase_DispatchInner+0x2d
0000000c`301df2b0 00007ffe`3103c7d9 clr!ManagedThreadBase_DispatchMiddle+0x6c
0000000c`301df3b0 00007ffe`3103c91b clr!ManagedThreadBase_DispatchOuter+0x75
0000000c`301df440 00007ffe`31146aba clr!ManagedThreadBase_FullTransitionWithAD+0x2f
0000000c`301df4a0 00007ffe`31153656 clr!ThreadNative::KickOffThread+0xd2
0000000c`301df570 00007ffe`38f113d2 clr!Thread::intermediateThreadProc+0x7d
0000000c`301df7b0 00007ffe`396454e4 kernel32!BaseThreadInitThunk+0x22
0000000c`301df7e0 00000000`00000000 ntdll!RtlUserThreadStart+0x34</span></pre>
&nbsp;

Ok, cool, so now how do we figure out which is the DLL that is currently being loaded? Well, from MSDN, we know that the first parameter passed to the <strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms684179(v=vs.85).aspx" rel="noopener noreferrer">kernelbase!LoadLibraryExW</a></strong> function is the name of the DLL (<strong>lpFileName</strong>).

Hmm ... first parameter ... so where is that? Well, we know that on x64 calling convention (<strong>fastcall</strong>), the first parameter is passed on into the <strong>RCX</strong> register: <a target="_blank" href="https://msdn.microsoft.com/en-us/library/ms235286.aspx" rel="noopener noreferrer">https://msdn.microsoft.com/en-us/library/ms235286.aspx</a>

So good! Let's have a look at that - as it should be a UNICODE string, we can look at it like this:
<pre class="trace"><span style="font-size: small"><strong>0:001&gt; du @rcx</strong>
0000000c`2f4dd240 "C:\Windows\assembly\NativeImages"
0000000c`2f4dd280 "_v4.0.30319_64\Microsoft.P521220"
0000000c`2f4dd2c0 "ea#\ab32ec62ecc4b90efc07602a8353"
0000000c`2f4dd300 "8c65\<strong>Microsoft.PowerShell.Comman</strong>"
0000000c`2f4dd340 "<strong>ds.Utility.ni.dll</strong>"</span></pre>
Pff ... well this is lame, not the correct DLL ... so we go again further until the next breakpoint with the "<strong>g</strong>" command and verify again and go again and verify and so on, until we finally reach the DLL we are interested in (in this case <strong><span style="color: #ff6600">NetworkDiscoveryModules.dll</span></strong>):
<pre class="trace"><span style="font-size: small"><strong>0:001&gt; g</strong>
Breakpoint 0 hit
<strong>kernelbase!LoadLibraryExW</strong>:
00007ffe`36b48d10 48895c2410 mov qword ptr [rsp+10h],rbx ss:0000000c`301dcbd8=0000000c301dddf8
<strong>0:001&gt; du @rcx</strong>
0000000c`301dd078 "C:\Program Files\Microsoft Syste"
0000000c`301dd0b8 "m Center 2012 R2\Operations Mana"
0000000c`301dd0f8 "ger\Server\<span style="color: #ff6600"><strong>NetworkDiscoveryModul</strong></span>"
0000000c`301dd138 "<span style="color: #ff6600"><strong>es.dll</strong></span>"</span></pre>
Perfect! Now we can put breakpoints on the other functions that will get called next to have a look (dependency) DLL by DLL to figure out which is corrupt and then go (continue execution):
<pre class="trace"><strong><span style="font-size: small">0:001&gt; bp ntdll!LdrpFindOrMapDll
0:001&gt; bp ntdll!ZwCreateSection
0:001&gt; g
</span></strong><span style="font-size: small">Breakpoint 2 hit
<strong>ntdll!LdrpFindOrMapDll</strong>:
00007ffe`396a61c0 4053            push    rbx</span></pre>
So, we break into the next call of <strong>ntdll!LdrpFindOrMapDll</strong>. Aaaaaand how exactly do we know which dependent DLL is being currently loaded? The function is not documented on MSDN ... ok, so a little bit of internals - this function gets the DLL name as a pointer to a string in the format of the <a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff564879(v=vs.85).aspx" rel="noopener noreferrer"><span style="color: #339966"><strong>ntdll!_UNICODE_STRING</strong></span></a> structure - which is actually documented on MSDN and which we can see using Public Symbols.

First parameter? Ok, so again, still in <strong>RCX</strong> register - let's dump it out using "<strong>dx</strong>" (<a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/native-objects-in-javascript-extensions" rel="noopener noreferrer">Debugger Data Model functionality</a> - <em>which can be extended using JavaScript as well - but a little later on extending it</em>):
<pre class="trace"><strong><span style="font-size: small">0:001&gt; dx ((ntdll!_UNICODE_STRING *)@rcx)
</span></strong><span style="font-size: small">((ntdll!_UNICODE_STRING *)0x00000000c301dc948) : 0xc301dc948 : "C:\Program Files\Microsoft System Center 2012 R2\Operations Manager\Server\<strong>NetworkDiscoveryModules.dll</strong>" [Type: _UNICODE_STRING *]
[&lt;Raw View&gt;] [Type: _UNICODE_STRING]</span></pre>
Ha, ok, now we're taking, we are going through the verification/load of our DLL of interest directly in <strong>ntdll!LdrpFindOrMapDll</strong>. Cool - so let's continue execution and we should break in <strong>ntdll!NtCreateSection</strong> next which we can use to verify the DLL consistency check status and see if there is any error (corruption in this case) - let's also have a look at the stack after we break:
<pre class="trace"><span style="font-size: small"><strong>0:001&gt; g</strong>
Breakpoint 1 hit
<strong>ntdll!NtCreateSection</strong>:
00007ffe`396c0b50 4c8bd1 mov r10,rcx

<strong>0:001&gt; k</strong>
Child-SP RetAddr Call Site
0000000c`301dc538 00007ffe`396a6921 <span style="color: #00ccff"><strong>ntdll!NtCreateSection</strong></span>
0000000c`301dc540 00007ffe`3965b2b5 <span style="color: #800080"><strong>ntdll!LdrpFindOrMapDll+0x761</strong></span>
0000000c`301dc8b0 00007ffe`39698d69 ntdll!LdrpLoadDll+0x295
0000000c`301dcae0 00007ffe`36b48dda ntdll!LdrLoadDll+0x99
0000000c`301dcb60 00007ffe`310ae4b4 <span style="color: #008000"><strong>kernelbase!LoadLibraryExW+0xca</strong></span>
0000000c`301dcbd0 00007ffe`310ae421 clr!CLRLoadLibraryExWorker+0x54
0000000c`301dcc20 00007ffe`31197dfd clr!CLRLoadLibraryEx+0x51
0000000c`301dcc70 00007ffe`3140bf1e clr!LocalLoadLibraryHelper+0x31
0000000c`301dcca0 00007ffe`310af2a4 clr!NDirect::LoadLibraryModule+0x35c7de
0000000c`301dd4f0 00007ffe`310af50a clr!NDirect::NDirectLink+0x80
0000000c`301dd820 00007ffe`310af469 clr!NDirect::GetStubForILStub+0x4a
0000000c`301dd870 00007ffe`310af54b clr!GetStubForInteropMethod+0x65
0000000c`301dd8b0 00007ffe`310a9696 clr!MethodDesc::DoPrestub+0xca7
0000000c`301dda80 00007ffe`3103226a clr!PreStubWorker+0x3d6
0000000c`301ddd90 00007ffd`d1a40a1c clr!ThePreStub+0x5a
0000000c`301dde60 00007ffe`2cb64c1c DynamicClass.CallSite.Target(System.Runtime.CompilerServices.Closure, System.Runtime.CompilerServices.CallSite, System.Type)+0xfc
0000000c`301ddee0 00007ffe`1938b088 system_core_ni!System.Dynamic.UpdateDelegates.UpdateAndExecute1[[System.__Canon, mscorlib],[System.__Canon, mscorlib]](System.Runtime.CompilerServices.CallSite, System.__Canon)+0x39c
0000000c`301ddff0 00007ffe`1938591b system_management_automation_ni!System.Management.Automation.Interpreter.DynamicInstruction`2[[System.__Canon, mscorlib],[System.__Canon, mscorlib]].Run(System.Management.Automation.Interpreter.InterpretedFrame)+0x58
0000000c`301de050 00007ffe`1938591b system_management_automation_ni!System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(System.Management.Automation.Interpreter.InterpretedFrame)+0x16b
0000000c`301de160 00007ffe`1938575b system_management_automation_ni!System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(System.Management.Automation.Interpreter.InterpretedFrame)+0x16b
0000000c`301de270 00007ffe`193752af system_management_automation_ni!System.Management.Automation.Interpreter.Interpreter.Run(System.Management.Automation.Interpreter.InterpretedFrame)+0x7b
0000000c`301de2f0 00007ffe`19383925 system_management_automation_ni!System.Management.Automation.Interpreter.LightLambda.RunVoid1[[System.__Canon, mscorlib]](System.__Canon)+0x11f
0000000c`301de380 00007ffe`193832f8 system_management_automation_ni!System.Management.Automation.DlrScriptCommandProcessor.RunClause(System.Action`1&lt;System.Management.Automation.Language.FunctionContext&gt;, System.Object, System.Object)+0x405
0000000c`301de510 00007ffe`19382fce system_management_automation_ni!System.Management.Automation.DlrScriptCommandProcessor.Complete()+0x1a8
0000000c`301de5c0 00007ffe`19382d01 system_management_automation_ni!System.Management.Automation.CommandProcessorBase.DoComplete()+0x16e
0000000c`301de680 00007ffe`19379551 system_management_automation_ni!System.Management.Automation.Internal.PipelineProcessor.DoCompleteCore(System.Management.Automation.CommandProcessorBase)+0xb1
0000000c`301de720 00007ffe`193666d0 system_management_automation_ni!System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(System.Object, System.Collections.Hashtable, Boolean)+0x191
0000000c`301de810 00007ffe`1936581f system_management_automation_ni!System.Management.Automation.Runspaces.LocalPipeline.InvokeHelper()+0x750
0000000c`301dea30 00007ffe`192e7001 system_management_automation_ni!System.Management.Automation.Runspaces.LocalPipeline.InvokeThreadProc()+0x2af
0000000c`301deb80 00007ffe`2f6d2d45 system_management_automation_ni!System.Management.Automation.Runspaces.PipelineThread.WorkerProc()+0x31
0000000c`301debb0 00007ffe`2f6d2ab9 mscorlib_ni!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x285
0000000c`301ded10 00007ffe`2f6d2a97 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)+0x9
0000000c`301ded40 00007ffe`2f6ea161 mscorlib_ni!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)+0x57
0000000c`301ded90 00007ffe`3103afb3 mscorlib_ni!System.Threading.ThreadHelper.ThreadStart()+0x51
0000000c`301dede0 00007ffe`3103ae9e clr!CallDescrWorkerInternal+0x83
0000000c`301dee20 00007ffe`3103b632 clr!CallDescrWorkerWithHandler+0x4a
0000000c`301dee60 00007ffe`31146bd9 clr!MethodDescCallSite::CallTargetWorker+0x251
0000000c`301df010 00007ffe`3103c8e1 clr!ThreadNative::KickOffThread_Worker+0x105
0000000c`301df270 00007ffe`3103c868 clr!ManagedThreadBase_DispatchInner+0x2d
0000000c`301df2b0 00007ffe`3103c7d9 clr!ManagedThreadBase_DispatchMiddle+0x6c
0000000c`301df3b0 00007ffe`3103c91b clr!ManagedThreadBase_DispatchOuter+0x75
0000000c`301df440 00007ffe`31146aba clr!ManagedThreadBase_FullTransitionWithAD+0x2f
0000000c`301df4a0 00007ffe`31153656 clr!ThreadNative::KickOffThread+0xd2
0000000c`301df570 00007ffe`38f113d2 clr!Thread::intermediateThreadProc+0x7d
0000000c`301df7b0 00007ffe`396454e4 kernel32!BaseThreadInitThunk+0x22
0000000c`301df7e0 00000000`00000000 ntdll!RtlUserThreadStart+0x34</span></pre>
Hmm, ok good! But what now? How do we figure out what the <strong>ntdll!NtCreateSection</strong> function will return? Because it will actually do a return of the status (which can be an error value). We know that by conversion, compilers will use the <strong>RAX</strong> register as return value just before finishing execution of a function (unless specifically coded otherwise in assembly).

Let's go at the end of the function execution of <strong>ntdll!NtCreateSection</strong> using "<strong>pt</strong>" and have a look at the value of the <strong>RAX</strong> register:
<pre class="trace"><span style="font-size: small"><strong>0:001&gt; pt</strong>
ntdll!NtCreateSection+0xa:
00007ffe`396c0b5a c3 ret

<strong>0:001&gt; r @rax</strong>
rax=<strong>0000000000000000</strong></span></pre>
Ok, so <strong>RAX</strong> is <strong>0</strong> and <strong>0</strong> is good! <strong>0</strong> means <strong>ERROR_SUCCESS</strong> status. Don't get confused by the name - it actually meas that <strong>the operation completed successfully</strong>: <a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx" rel="noopener noreferrer">https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85).aspx</a>

So, we don't throw an error and we validate this DLL (currently <strong><span style="color: #ff6600">NetworkDiscoveryModules.dll</span></strong>) successfully. Ok, so next, we should go through each dependent DLL and try to validate/load each on of them. So, let's step through each one of these and check the status (return value in <strong>RAX</strong>) of <strong>ntdll!NtCreateSection</strong> each time.

So after checking each one (<strong>ntdll!LdrpFindOrMapDll</strong> for the DLL name &amp; <strong>ntdll!NtCreateSection</strong> for the return value) we finally reach the DLL that is throwing the error (binary file validation error):
<pre class="trace"><span style="font-size: small"><strong>0:001&gt; g</strong>
Breakpoint 2 hit
<strong>ntdll!LdrpFindOrMapDll</strong>:
00007ffe`396a61c0 4053 push rbx

<strong>0:001&gt; dx ((ntdll!_UNICODE_STRING *)@rcx)</strong>
((ntdll!_UNICODE_STRING *)@rcx) : 0xc301dc4b0 : "<span style="color: #ff0000"><strong>dmboot.dll</strong></span>" [Type: _UNICODE_STRING *]
[&lt;Raw View&gt;] [Type: _UNICODE_STRING]

<strong>0:001&gt; g</strong>
Breakpoint 1 hit
<strong>ntdll!NtCreateSection</strong>:
00007ffe`396c0b50 4c8bd1 mov r10,rcx

<strong>0:001&gt; pt</strong>
<strong>ntdll!NtCreateSection+0xa</strong>:
00007ffe`396c0b5a c3 ret

<strong>0:001&gt; r @rax</strong>
rax=<span style="color: #ff0000"><strong>00000000c000012f</strong></span></span></pre>
Ha, nice! So return status for <strong>ntdll!NtCreateSection</strong> for the <span style="color: #ff0000"><strong>dmboot.dll</strong></span>  DLL is not <strong>0 </strong>(<strong>ERROR_SUCCESS</strong>) anymore - it is: <span style="color: #ff0000"><strong>00000000c000012f</strong></span>

Guess what? We also have a command from a build-in extension (<strong>!error</strong>) for WinDbg which we can use to "resolve" the actual error name/description by the HRESULT (<span style="color: #ff0000"><strong>00000000c000012f</strong></span>) value:
<pre class="trace"><span style="font-size: small"><strong>0:001&gt; !error 00000000c000012f</strong>
Error code: (NTSTATUS) <span style="color: #ff0000"><strong>0xc000012f</strong></span> (3221225775) - <span style="color: #ff0000"><strong>The specified image file did not have the correct format, it did not have an initial MZ.</strong></span></span></pre>
&nbsp;

Well ... what do you know? It looks like the <span style="color: #ff0000"><strong>dmboot.dll</strong></span> DLL is the one that is actually corrupt and it is being loaded because it is a dependency DLL of our <strong><span style="color: #ff6600">NetworkDiscoveryModules.dll</span></strong> DLL.

We got the <span style="color: #ff0000"><strong>dmboot.dll</strong></span> DLL from a healthy SCOM Management Server with the same SCOM version and Update Rollup and replaced this corrupt one - aaand ... there you go, <span style="color: #008000"><strong>issue solved</strong></span>! :D

<a href="https://msdnshared.blob.core.windows.net/media/2017/06/gs.jpg"><img src="https://msdnshared.blob.core.windows.net/media/2017/06/gs.jpg" alt="" width="295" height="340" class="size-full wp-image-1025 aligncenter" /></a>

&nbsp;

&nbsp;

How did this file (DLL) get corrupt in the first place?! Well now, that is the real question! Unfortunately, it cannot really be explained after it already happened without any type of "file-change-auditing", but it has too many possible causes:
<ul>
 	<li>some filter driver (like anti-virus software or anything else like "my-super-cool-awesome-disk-speed-up.sys" and so on ...</li>
 	<li>computer power-failure in the middle of specific type of disk IO (direct access) - very unlikely though ...</li>
 	<li>network (possibly filter) driver while copying a file from some other computer (or some network device in between that somehow ends up modifying bits)</li>
 	<li>super cool awesome storage controller that directly manipulates (RAM) memory through the mother board (not through OS Kernel)</li>
 	<li>some totally other random weird issue like a CPU bit-flip while the file was being written to disk ?! ...</li>
</ul>
&nbsp;

Yes - this gets much easier if Private Symbols are available ;) But, as this should (I hope) ideally help anyone trying to debug such a scenario, I have documented everything using Public Symbols :D

But hey ... why not automate this process by creating a cool JavaScript extension for WinDbg and just let the computer do the work for me next time this ever happens with ... whatever ... other software? :D

Here is the documentation about creating extensions in JavaScript for the Data Model: <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/javascript-debugger-scripting" rel="noopener noreferrer">https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/javascript-debugger-scripting</a> &amp; also check out this <a target="_blank" href="https://channel9.msdn.com/" rel="noopener noreferrer"><strong>Channel9</strong> </a>video from the <a target="_blank" href="https://channel9.msdn.com/Shows/Defrag-Tools" rel="noopener noreferrer"><strong>Defrag Tools series</strong></a> about this, with cool info from <em>Andrew Richards</em>, <em>Andy Luhrs</em> and <em>Bill Messmer</em>: <a target="_blank" href="https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-170-Debugger-JavaScript-Scripting" rel="noopener noreferrer">https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-170-Debugger-JavaScript-Scripting</a>

This could have easily been just a series of functions in the scripts, but I complicated it a little bit because I wanted to show it as an extension to the process object - I might extend this in the future and create a more complex extension around the LDR component. I highly doubt that it will be public though :p because without public symbols, I have to rely on calling conversions (and get directly directly from registers when possible - and it's not always possible) as I cannot resolve any locals or parameters (by calling DX's <strong>getModuleSymbol</strong>), which would over-complicate things.
<pre class="trace"><span style="font-size: small">"use strict";

class __DllLoadStatus
{
   get Ldr()
   {
      return new __DllLoadFailure(this);
   }
}

class __DllLoadFailure
{
   constructor(process)
   {
      this.__process = process;
   }

   Initialize()
   {
      var ctl = host.namespace.Debugger.Utility.Control;
      ctl.ExecuteCommand("bp /1 ntdll!ZwCreateSection;g");
      ctl.ExecuteCommand("pt");

      var address = host.currentThread.Registers.User.rip;
      ctl.ExecuteCommand("bp ntdll!LdrpFindOrMapDll \"dx @$curprocess.Ldr.GetDllName();gc\"");
      ctl.ExecuteCommand("bp " + address.toString(16) + " \"dx @$curprocess.Ldr.GetLoadStatus();gc\"");

      host.diagnostics.debugLog("Ok, we are all set! Run \"g\" to start automated debugging.\n");
   }

   GetDllName()
   {
      var ctl = host.namespace.Debugger.Utility.Control;
      var address = host.currentThread.Registers.User.rcx;

      var pDllName = host.createPointerObject(address, "ntdll.dll", "_UNICODE_STRING *");
      var dllName = host.memory.readWideString(pDllName.dereference().Buffer).toString();

      host.diagnostics.debugLog(dllName, "\n");
   }

   GetLoadStatus()
   {
      var ctl = host.namespace.Debugger.Utility.Control;
      var status = ctl.ExecuteCommand("!error @rax").First().toString();

      host.diagnostics.debugLog(status, "\n");
   }
}

function initializeScript()
{
   return [
      new host.namedModelParent(__DllLoadStatus, "Debugger.Models.Process")
   ];
}</span></pre>
Alright, so now we have this script saved somewhere (ex. C:\DbgScripts\LdrExtensionSample.js). So let's load the JsProvider (<strong>!load jsprovider</strong>) and afterwards using the full path of the script as parameter, load the script using the <strong>.scriptload</strong> command:
<pre class="trace"><span style="font-size: small">0:004&gt; <strong>!load jsprovider</strong>
0:004&gt; <strong>.scriptload C:\DbgScripts\LdrExtensionTest.js</strong>
JavaScript script successfully loaded from 'C:\DbgScripts\LdrExtensionTest.js'</span></pre>
So, let's have a go at our script and see the output of the automated analysis by running "<strong>dx @$curprocess.Ldr.Initialize()</strong>" and then letting the process execute with the "<strong>g</strong>" command:
<pre class="trace"><span style="font-size: small">0:000&gt; <strong>dx @$curprocess.Ldr.Initialize()</strong>
<strong>Ok, we are all set! Run "g" to start automated debugging.</strong>
@$curprocess.Ldr.Initialize()
 
0:001&gt; <strong>g</strong>
C:\Windows\system32\rsaenh.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
C:\Program Files\Microsoft System Center 2012 R2\Operations Manager\Server\<span style="color: #ff6600"><strong>NetworkDiscoveryModules.dll</strong></span>
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
MSVCR100.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
KERNEL32.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
USER32.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
ole32.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
OLEAUT32.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
ADVAPI32.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
sm-server.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
sm-discovery.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
sm-auto-discovery.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
MSVCP100.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
ntdll.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
RPCRT4.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
SHLWAPI.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
HealthServiceRuntime.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
KERNEL32.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
MSVCP100.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
MSVCR100.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
KERNEL32.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
ADVAPI32.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
sm-clsapi.dll
@$curprocess.Ldr.GetDllName()
Error code: (Win32) 0 (0) - The operation completed successfully.
@$curprocess.Ldr.GetLoadStatus()
<span style="color: #ff0000"><strong>dmboot.dll</strong></span>
@$curprocess.Ldr.GetDllName()
<span style="color: #ff0000"><strong>Error code: (NTSTATUS) 0xc000012f (3221225775) - The specified image file did not have the correct format, it did not have an initial MZ.</strong></span>
@$curprocess.Ldr.GetLoadStatus()</span></pre>
&nbsp;

Pfff ... well, that was much easier :D

&nbsp;

Have fun developing WinDbg JS Extensions &amp; Scripts! :)

&nbsp;

&nbsp;

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>SCCM Server hangs due to memory pressure (Kernel Cache Manager)</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/sccm-server-hangs-due-to-memory-pressure-kernel-cache-manager</link>
      <pubDate>Tue, 04 Jul 2017 09:08:47 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/?p=1095</guid>
      <description><![CDATA[Got a request the other day to have a look at a full memory dump of a SCCM server that was hanging...]]></description>
      <content:encoded><![CDATA[Got a request the other day to have a look at a full memory dump of a SCCM server that was hanging due to physical memory pressure (has <strong>32GB RAM</strong> installed).

As it is the case usually in these situations, the issue was not caused by any SCCM component, but rather something else ;)

It's a good opportunity though to discuss a little bit about the <a target="_blank" href="https://channel9.msdn.com/Shows/Going+Deep/Windows-NT-Cache-Manager-Molly-Brown-Part-II">Windows Kernel Cache Manager</a>. Everything will be done with <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/microsoft-public-symbols">Public Symbols</a> as usual and also the heavy use of the <a target="_blank" href="https://www.microsoft.com/en-us/download/details.aspx?id=53304">MEX Debugger Extension</a> (showing it's power as well :D ).

<span style="color: #ff0000"><strong>Note:</strong></span> Even if I am using Public Symbols, I am using <strong>WinDe</strong> dbg extension which is available for some customers under NDA. Some <strong>MEX</strong> dbg extensions also will not work because they rely on <strong>WinDe</strong> dbg extension. One of these commands is <span style="color: #0000ff"><strong>!mex.mem</strong></span>. I will use this one for simplicity's sake as the output is structured and easy to see. If these are not available, you will need to use <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-memusage"><span style="color: #ff6600"><strong>!kdexts.memusage </strong></span></a>or even better, the <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-vm"><span style="color: #008000"><strong>!kdexts.vm </strong></span></a>command. I will use <strong>WinDe</strong>/<strong>MEX</strong> because the output is much nicer to see :p But, you can achieve the same with the build-in commands mentioned.

&nbsp;

First pf all, let's start by checking the memory status of the server - we can do this by running <span style="color: #0000ff"><strong>!mex.mem</strong></span>
<pre class="trace"><span style="font-size: small">5: kd&gt;<strong> <span style="color: #0000ff">!mex.mem</span></strong>
Page File: \??\C:\pagefile.sys
Current: 10794940 Kb Free Space: 6592416 Kb ( 10.29 GB)
Minimum: 10794940 Kb Maximum: 10794940 Kb ( 10.29 GB)

Physical Memory: 8385237 ( 33540948 Kb) ( 31.99 GB)
<strong><span style="color: #ff0000">Available Pages: 27177 ( 108708 Kb) ( 106.16 MB)</span></strong>
ResAvail Pages: 8193973 ( 32775892 Kb) ( 31.26 GB)
Locked IO Pages: 0 ( 0 Kb) ( 0)
Free System PTEs: 33514422 ( 134057688 Kb) ( 127.85 GB)
<span style="color: #ff0000"><strong>Modified Pages: 4073135 ( 16292540 Kb) ( 15.54 GB)</strong></span>
Modified PF Pages: 3 ( 12 Kb) ( 12.00 KB)
Modified No Write Pages: 0 ( 0 Kb) ( 0)
NonPagedPool 0: 8326 ( 33304 Kb) ( 32.52 MB)
NonPagedPool 1: 6844 ( 27376 Kb) ( 26.73 MB)
NonPagedPool 2: 0 ( 0 Kb) ( 0)
NonPagedPool 3: 0 ( 0 Kb) ( 0)
NonPagedPool Usage: 36694 ( 146776 Kb) ( 143.34 MB) Current pool size: 981.94 MB
NonPagedPool Max: 6263793 ( 25055172 Kb) ( 23.89 GB)
PagedPool 0: 107157 ( 428628 Kb) ( 418.58 MB)
PagedPool 1: 12274 ( 49096 Kb) ( 47.95 MB)
PagedPool 2: 6081 ( 24324 Kb) ( 23.75 MB)
PagedPool 3: 0 ( 0 Kb) ( 0)
PagedPool 4: 38 ( 152 Kb) ( 152.00 KB)
PagedPool Usage: 125550 ( 502200 Kb) ( 490.43 MB) WorkingSet: 286.58 MB, PeakWorkingSet: 517.27 MB
PagedPool Maximum: 33554432 ( 134217728 Kb) ( 128.00 GB)
Processor Commit: 3751 ( 15004 Kb) ( 14.65 MB)
Session Commit: 12901 ( 51604 Kb) ( 50.39 MB)
Syspart SharedCommit 0
Shared Commit: 17255 ( 69020 Kb) ( 67.40 MB)
Special Pool: 0 ( 0 Kb) ( 0)
Kernel Stacks: 13455 ( 53820 Kb) ( 52.56 MB)
Pages For MDLs: 1859 ( 7436 Kb) ( 7.26 MB)
Pages For AWE: 0 ( 0 Kb) ( 0)
NonPagedPool Commit: 0 ( 0 Kb) ( 0)
PagedPool Commit: 125678 ( 502712 Kb) ( 490.93 MB)
Driver Commit: 4240 ( 16960 Kb) ( 16.56 MB)
Boot Commit: 0 ( 0 Kb) ( 0)
System PageTables: 0 ( 0 Kb) ( 0)
VAD/PageTable Bitmaps: 3882 ( 15528 Kb) ( 15.16 MB)
ProcessLockedFilePages: 0 ( 0 Kb) ( 0)
Pagefile Hash Pages: 0 ( 0 Kb) ( 0)
Sum System Commit: 183021 ( 732084 Kb) ( 714.93 MB)
Total Private: 5012200 ( 20048800 Kb) ( 19.12 GB)
Misc/Transient Commit: 170655 ( 682620 Kb) ( 666.62 MB)
Committed pages: 5365876 ( 21463504 Kb) ( 20.47 GB)
Commit limit: 11083507 ( 44334028 Kb) ( 42.28 GB)

<strong><span style="color: #ff0000">*** Low Available Pages (Standby+Zeroed+Free). This can cause performance issues. ***</span></strong>

Virtual Memory Physical Memory File Cache Cache Writes</span></pre>
Notice these 2 interesting things from the output:
<ul>
 	<li><span style="color: #ff0000"><strong>Available Pages: 27177 ( 108708 Kb)   ( 106.16 MB)</strong></span>           =&gt; so we only have 106.16 MB free physical memory (pages) ...</li>
 	<li><span style="color: #ff0000"><strong>Modified Pages: 4073135 ( 16292540 Kb)   ( 15.54 GB)</strong> </span>     =&gt; from 32 GB total physical memory, we have 15.54 GB (half of the memory) in <a target="_blank" href="https://blogs.msdn.microsoft.com/tims/2010/10/29/pdc10-mysteries-of-windows-memory-management-revealed-part-two/">Modified Pages</a></li>
</ul>
What is the <span><strong>MiModifiedPageWriter</strong> (<a target="_blank" href="https://blogs.msdn.microsoft.com/tims/2010/10/29/pdc10-mysteries-of-windows-memory-management-revealed-part-two/">Modified Page Writer</a>) thread (running in System context) doing - is it blocked by anything?</span>

To switch to the <strong>System</strong> process, we need to find it's address - we can do this by using <span style="color: #0000ff"><strong>!mex.tl</strong></span> and passing it the name of the process we are interested in:
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.tl system</strong></span>
PID Address Name
=========== ================ =========================================
0x4 0n4 <span style="color: #008000"><strong>fffffa8019a6b040</strong> </span>System
0x1b8 0n440 fffffa8028f02060 svchost.exe(LocalSystemNetworkRestricted)
=========== ================ =========================================
PID Address Name

Warning! Zombie process(es) detected (not displayed). Count: 2 [zombie report]</span></pre>
Ok, got it (<span style="color: #008000"><strong>fffffa8019a6b040</strong></span>) - let's switch to it by running <span style="color: #0000ff"><strong>!mex.p</strong></span> and passing it this address:
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.p <span style="color: #008000">fffffa8019a6b040</span></strong></span>
Name Address Ses PID User Name Create Time Up Time Mods Handle Act Thrd Z Thrd Parent
====== ================ ==== ======= =============== ========================== ============ ==== ====== ======== ====== ==============
<strong>System</strong> fffffa8019a6b040 none 4 (0n4) DOMAIN\COMPUTERNAME$ 06/26/2017 12:11:57.995 PM 2h:03:22.004 0 1176 204 0 Idle 0 (0n0)

Memory Details:

VM Peak Work Set Commit Size
======== ======== ======== ===========
23.18 MB 27.99 MB 18.49 MB 556 KB

CPU Details:

User Kernel Total
==== ========== ==========
0s 24m:33.696 24m:33.696

Show Threads: Unique Stacks !mex.listthreads (!lt) fffffa8019a6b040 !winde.lp fffffa8019a6b040 !process fffffa8019a6b040 7</span></pre>
Right! We are in the context of the <strong>System</strong> process, let's find the Modified Page Writer thread - it should have this function call on the stack "<span style="color: #ff6600"><strong>nt!MiModifiedPageWriter</strong></span>".

Being in the context of the <strong>System</strong> process we can use MEX again to search in all available threads for a thread stack that matches what we are looking for - we can use <span style="color: #0000ff"><strong>!mex.us</strong></span> and pass it the string we are looking for "<span style="color: #ff6600"><strong>nt!MiModifiedPageWriter</strong></span>":
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.us</strong></span> <span style="color: #ff6600"><strong>nt!MiModifiedPageWriter</strong></span>
1 thread [stats]: <span style="color: #ff00ff"><strong>fffffa8019ab43c0</strong></span>
fffff80001eda6aa nt!KiSwapContext+0x7a
fffff80001edd142 nt!KiCommitThreadWait+0x1d2
fffff80001e9c03b <strong>nt!KeWaitForGate</strong>+0xfb
fffff80001e73c3a <span style="color: #ff6600"><strong>nt!MiModifiedPageWrite</strong></span>r+0x5a
fffff80002170f12 nt!PspSystemThreadStartup+0x5a
fffff80001ec9de6 nt!KiStartSystemThread+0x16

Threads matching filter: 1 out of 204</span></pre>
Cool, found it! Now we want to see more information about what this thread is doing, it's state, etc. We can do this with <span style="color: #0000ff"><strong>!mex.t</strong></span> and passing it the thread address (<span style="color: #ff00ff"><strong>fffffa8019ab43c0</strong></span>):
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.t</strong></span> <span style="color: #ff00ff"><strong>fffffa8019ab43c0</strong></span>
Process Thread CID UserTime KernelTime ContextSwitches Wait Reason Time
System (fffffa8019a6b040) fffffa8019ab43c0 4.ac 0s 1s.154 3135 WrFreePage 3s.650

WaitBlockList:
Object Name Type Other Waiters
<span style="color: #339966"><strong>fffff80002092e00</strong> </span><span style="color: #008000"><strong>nt!MmModifiedPageWriterGate</strong></span>+0x0 Gate 0

Priority:
Current Base UB FB IO Page
17 8 0 0 2 5

# Child-SP Return Call Site
0 fffff880029fdac0 fffff80001edd142 nt!KiSwapContext+0x7a
1 fffff880029fdc00 fffff80001e9c03b nt!KiCommitThreadWait+0x1d2
2 fffff880029fdc90 fffff80001e73c3a <strong>nt!KeWaitForGate</strong>+0xfb
3 fffff880029fdce0 fffff80002170f12 <span style="color: #ff6600"><strong>nt!MiModifiedPageWriter</strong></span>+0x5a
4 fffff880029fdd40 fffff80001ec9de6 nt!PspSystemThreadStartup+0x5a
5 fffff880029fdd80 0000000000000000 nt!KiStartSystemThread+0x16</span></pre>
It's not blocked by anything, it is just waiting on <span><span style="color: #008000"><strong>nt!MmModifiedPageWriterGate</strong></span> which is a (<span style="color: #008000"><strong>nt!_KGATE</strong></span>)</span> <a target="_blank" href="http://www.codemachine.com/article_kernelstruct.html">Gate object</a> (short said, event to get triggered to start doing work) - we can have a look at the Gate object using <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/dx--display-visualizer-variables-"><span style="color: #0000ff"><strong>dx</strong></span></a> and passing it the address (<span style="color: #339966"><strong>fffff80002092e00</strong></span>):
<pre class="trace"><span style="font-size: small">0: kd&gt; <span style="color: #0000ff"><strong>dx -r1 ((nt!_KGATE *)</strong></span><span style="color: #339966"><strong>0xfffff80002092e00</strong></span><span style="color: #0000ff"><strong>)</strong></span>
((nt!_KGATE *)0xfffff80002092e00)                 : 0xfffff80002092e00 [Type: _KGATE *]
    [+0x000] <span style="color: #0000ff"><strong>Header          </strong> </span>[Type: _DISPATCHER_HEADER]

0: kd&gt; <span style="color: #0000ff"><strong>dx -r1 ((ntkrnlmp!_DISPATCHER_HEADER *)</strong></span><span style="color: #339966"><strong>0xfffff80002092e00</strong></span><span style="color: #0000ff"><strong>)</strong></span>
((ntkrnlmp!_DISPATCHER_HEADER *)0xfffff80002092e00)                 : 0xfffff80002092e00 [Type: _DISPATCHER_HEADER *]
    [+0x000] Type             : 0x7 [Type: unsigned char]
    [+0x001] TimerControlFlags : 0x1 [Type: unsigned char]
    [+0x001 ( 0: 0)] Absolute         : 0x1 [Type: unsigned char]
    [+0x001 ( 1: 1)] Coalescable      : 0x0 [Type: unsigned char]
    [+0x001 ( 2: 2)] KeepShifting     : 0x0 [Type: unsigned char]
    [+0x001 ( 7: 3)] EncodedTolerableDelay : 0x0 [Type: unsigned char]
    [+0x001] Abandoned        : 0x1 [Type: unsigned char]
    [+0x001] Signalling       : 0x1 [Type: unsigned char]
    [+0x002] ThreadControlFlags : 0x6 [Type: unsigned char]
    [+0x002 ( 0: 0)] CpuThrottled     : 0x0 [Type: unsigned char]
    [+0x002 ( 1: 1)] CycleProfiling   : 0x1 [Type: unsigned char]
    [+0x002 ( 2: 2)] CounterProfiling : 0x1 [Type: unsigned char]
    [+0x002 ( 7: 3)] Reserved         : 0x0 [Type: unsigned char]
    [+0x002] Hand             : 0x6 [Type: unsigned char]
    [+0x002] Size             : 0x6 [Type: unsigned char]
    [+0x003] TimerMiscFlags   : 0x0 [Type: unsigned char]
    [+0x003 ( 5: 0)] Index            : 0x0 [Type: unsigned char]
    [+0x003 ( 6: 6)] Inserted         : 0x0 [Type: unsigned char]
    [+0x003 ( 7: 7)] Expired          : 0x0 [Type: unsigned char]
    [+0x003] DebugActive      : 0x0 [Type: unsigned char]
    [+0x003 ( 0: 0)] ActiveDR7        : 0x0 [Type: unsigned char]
    [+0x003 ( 1: 1)] Instrumented     : 0x0 [Type: unsigned char]
    [+0x003 ( 5: 2)] Reserved2        : 0x0 [Type: unsigned char]
    [+0x003 ( 6: 6)] UmsScheduled     : 0x0 [Type: unsigned char]
    [+0x003 ( 7: 7)] UmsPrimary       : 0x0 [Type: unsigned char]
    [+0x003] DpcActive        : 0x0 [Type: unsigned char]
    [+0x000] Lock             : 393479 [Type: long]
    [+0x004] SignalState      : 0 [Type: long]
    [+0x008] WaitListHead     [Type: _LIST_ENTRY]
</span></pre>
Hmm, what else? Well we also have another system thread that is writing modified pages (aka dirty pages) - this is being used to write <a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa366556(v=vs.85).aspx">memory mapped files</a> that have been modified (<em>these are usually being backed by the<strong> page file</strong></em>) - <span style="color: #ff6600"><strong>nt!MiMappedPageWriter</strong></span> - same as before <span style="color: #0000ff"><strong>!mex.us</strong></span>) and then using <span style="color: #0000ff"><strong>!mex.t</strong></span> to have more detailed information:
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.us</strong></span> <span style="color: #ff6600"><strong>nt!MiMappedPageWriter</strong></span>
1 thread [stats]: <span style="color: #ff00ff"><strong>fffffa8019ab5040</strong></span>
fffff80001eda6aa nt!KiSwapContext+0x7a
fffff80001edd142 nt!KiCommitThreadWait+0x1d2
fffff80001ede056 nt!KeDelayExecutionThread+0x186
fffff80001f117bc nt!MiGatherMappedPages+0x8c
fffff80001f122f8 nt!MiMappedPageWriter+0x198
fffff80002170f12 nt!PspSystemThreadStartup+0x5a
fffff80001ec9de6 nt!KiStartSystemThread+0x16

Threads matching filter: 1 out of 204
5: kd&gt; <span style="color: #0000ff"><strong>!mex.t</strong></span> <span style="color: #ff00ff"><strong>fffffa8019ab5040</strong></span>
Process Thread CID UserTime KernelTime ContextSwitches Wait Reason Time
<strong>System</strong> (fffffa8019a6b040) fffffa8019ab5040 4.b0 0s 187ms 133350 DelayExecution 15ms

Priority:
Current Base UB FB IO Page
17 8 0 0 2 5

# Child-SP Return Call Site
0 fffff88002b08910 fffff80001edd142 nt!KiSwapContext+0x7a
1 fffff88002b08a50 fffff80001ede056 nt!KiCommitThreadWait+0x1d2
2 fffff88002b08ae0 fffff80001f117bc <span style="color: #808000"><strong>nt!KeDelayExecutionThread</strong></span>+0x186
3 fffff88002b08b50 fffff80001f122f8 nt!MiGatherMappedPages+0x8c
4 fffff88002b08c50 fffff80002170f12 <span style="color: #ff6600"><strong>nt!MiMappedPageWriter</strong></span>+0x198
5 fffff88002b08d40 fffff80001ec9de6 nt!PspSystemThreadStartup+0x5a
6 fffff88002b08d80 0000000000000000 nt!KiStartSystemThread+0x16</span></pre>
Also not blocked, it's normally waiting in <span><span style="color: #808000"><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff551986(v=vs.85).aspx"><strong>nt!KeDelayExecutionThread</strong></a></span> which means that after some time, it will run again and then wait again and so on (it basically runs on an interval).</span>

But what files are being currently cached and how big are they in memory? We can have a look at this using <strong><span style="color: #0000ff">!mex.mem -fc</span> </strong>and we get this here:
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.mem -fc</strong></span>
Name <span style="color: #800080"><strong>ControlArea</strong> </span>FsContext Valid <span style="color: #ff0000"><strong>StandbyDirty</strong> </span>Shared Locked Total
=================================================================================== ================ ================ ======== ============ ====== ====== ========
<em>[...SNIPPED...]</em>
$LogFile fffffa801fc6b990 fffffa801f656e10 860 KB 860 KB
CM_123.mdf fffffa802a3dd490 fffff8a003a85140 1.75 MB 1.75 MB
$Mft fffffa801ce9d4a0 fffffa801ce7dbb0 2.82 MB 2.82 MB
<strong><span style="color: #ff0000">CM_123.mdf</span> <span style="color: #800080">fffffa80204ffd30</span> fffff8a003423140 10.69 MB <span style="color: #ff0000">15.54</span> GB 15.55 GB</strong>

Virtual Memory Physical Memory File Cache Cache Writes</span></pre>
Interesting ... there is a file called <strong>CM_123.mdf</strong> that is using 15.54GB - that is half of our physical memory !!! Ha, there we have it!

Let's have a look at more details (ex. it's path, etc.). This address (<span style="color: #800080"><strong>fffffa80204ffd30</strong></span>) to the file will point to a <span style="color: #800080"><strong>Control Area</strong> </span>which is s structure the Kernel creates for the image file - we can use <span style="color: #0000ff"><strong>!kdexts.ca</strong></span> with this address and get more information:
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!kdexts.ca</strong></span> <span style="color: #800080"><strong>fffffa80204ffd30</strong></span>
ControlArea @ fffffa80204ffd30
Segment fffff8a004a8b940 Flink 0000000000000000 Blink 0000000000000000
Section Ref 1 Pfn Ref 3e30f0 Mapped Views 19f
User Ref 0 WaitForDel 0 Flush Count 0
File Object fffffa802a4144f0 ModWriteCount 0 System Views 19f
WritableRefs 0
Flags (8080) File WasPurged

<span style="color: #ff0000"><strong>\SCCMSQLBackup\123Backup\SiteDBServer\CM_123.mdf</strong></span>

Segment @ fffff8a004a8b940
ControlArea fffffa80204ffd30 ExtendInfo 0000000000000000
Total Ptes 1745000
Segment Size 1745000000 Committed 0
Flags (c0000) ProtectionMask

Subsection 1 @ fffffa80204ffdb0
ControlArea fffffa80204ffd30 Starting Sector 0 Number Of Sectors 800000
Base Pte fffff8a014a00000 Ptes In Subsect 800000 Unused Ptes 0
Flags d Sector Offset 0 Protection 6
Accessed
Flink fffffa801fc069d0 Blink fffffa802a3dd560 MappedViews 0

Subsection 2 @ fffffa801fc0a010
ControlArea fffffa80204ffd30 Starting Sector 800000 Number Of Sectors 800000
Base Pte fffff8a01ca00000 Ptes In Subsect 800000 Unused Ptes 0
Flags d Sector Offset 0 Protection 6
Accessed
Flink 0000000000000000 Blink 0000000000000000 MappedViews 19f

Subsection 3 @ fffffa801fc54b30
ControlArea fffffa80204ffd30 Starting Sector 1000000 Number Of Sectors 745000
Base Pte 0000000000000000 Ptes In Subsect 745000 Unused Ptes 0
Flags c Sector Offset 0 Protection 6
Flink 0000000000000000 Blink 0000000000000000 MappedViews 0</span></pre>
It really seems to be something related to SCCM - but which process is holding this file?

In this moment, I am guessing that we are already doing Cache Write Throttling - this is a mechanism used to improve server performance when we may delay the writes. This is something that will be triggered when nt!CcTotalDirtyPages will be bigger than nt!CcDirtyPageThreshold.

From the Windows Internals book:

"<em>The file system and cache manager must determine whether a cached write request will affect system performance and then schedule any delayed writes. First the file system asks the cache manager whether a certain number of bytes can be written right now without hurting performance by using the <strong>CcCanIWrite</strong> function and blocking the write if necessary. For asynchronous I/O, the file system sets up a callback with the cache manager for automatically writing the bytes when writes are again permitted by calling <strong>CcDeferWrite</strong>. Otherwhise, it just blocks and waits on <strong>CcCanIWrite</strong> to continue. Once it's notified of an impending write operation, the cache manager determines how many firty pages are in the cache and how much physical memory is available. If few physical pages are free, the cache manager momentarily blocks the file system thread that's requesting to write data to the cache. The cache manager's lazy writer flushes some of the dirty pages to disk and then allows the blocked file system thread to continue. This throttling prevents system performance from degrading because of a lack of memory when a file system or network server issues a large write operation</em>".

We have a very cool command we can use to check this which will also show us which (if any) files are currently in this state (from where we can get the file handle) - <span style="color: #0000ff"><strong>!kdexts.defwrites</strong></span>:
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!kdexts.defwrites</strong></span>
<strong>*** Cache Write Throttle Analysis ***</strong>

CcTotalDirtyPages: 4075797 (16303188 Kb)
CcDirtyPageThreshold: 4058054 (16232216 Kb)
AvailablePages: 27177 ( 108708 Kb)
ThrottleTop: 450 ( 1800 Kb)
ThrottleBottom: 80 ( 320 Kb)
ModifiedPages: 4073135 (16292540 Kb)

<span style="color: #ffcc00"><strong>CcTotalDirtyPages &gt;= CcDirtyPageThreshold, writes throttled</strong></span>

Check these thread(s): CcWriteBehind(LazyWriter)
Check critical workqueue for the lazy writer, !exqueue 16
Cc Deferred Write list: (CcDeferredWrites)
<strong>File: <span style="color: #ff00ff">fffffa802a4144f0</span> Event: fffff880074906d0
File: <span style="color: #cc99ff">fffffa8029c08070</span> Event: fffff88007968640</strong></span></pre>
Yup, sure enough, we are currently doing throttling and here are the 2 file handles we have <span><span style="color: #ff00ff"><strong>fffffa802a4144f0</strong> </span>&amp; <span style="color: #cc99ff"><strong>fffffa8029c08070</strong></span>.</span>

Nice, so now that we have the handles, we can use <span style="color: #0000ff"><strong>!kdexts.fileobj</strong></span> and give it the address to understand what files these are:
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!kdexts.fileobj</strong></span> <span style="color: #ff00ff"><strong>fffffa802a4144f0</strong></span>

<span style="color: #ff0000"><strong>\SCCMSQLBackup\123Backup\SiteDBServer\CM_123.mdf</strong></span>

Device Object: 0xfffffa801f7d07c0 \Driver\volmgr
Vpb: 0xfffffa8029683ad0
Event signalled
Access: Read Write Delete

Flags: 0x43062
Synchronous IO
Sequential Only
Cache Supported
Modified
Size Changed
Handle Created

File Object is currently busy and has 0 waiters.

FsContext: 0xfffff8a003423140 FsContext2: 0xfffff8a00f5d3500
Private Cache Map: 0xfffffa802029b9c0
CurrentByteOffset: edb0f0000
Cache Data:
Section Object Pointers: fffffa8029479818
Shared Cache Map: fffffa802029b850 File Offset: ffffffffdb0f0000</span></pre>
Ha! Exactly the one we are looking for (using <span style="color: #ff0000"><strong>15.54GB</strong></span> of RAM): <span style="color: #ff0000">\<strong>SCCMSQLBackup\123Backup\SiteDBServer\CM_123.mdf</strong></span>

No need to look at the other one now, it's the one we are interested in. So ok, what SCCM process is currently having a handle open on this file? We can use <span style="color: #0000ff"><strong>!mex.findhandle</strong></span> with the address of the file handle (<span style="color: #ff00ff"><strong>fffffa802a4144f0</strong></span>) to get the process (you can use <strong>!kdexts.findhandle</strong> instead):
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.findhandle</strong></span> <span style="color: #ff00ff"><strong>fffffa802a4144f0</strong></span>
<strong><span style="color: #993300">smssqlbkup.exe</span> <span style="color: #993300">fffffa802935eb10</span></strong>
384</span></pre>
Ok, let's have a look at what this SCCM process (<span style="color: #993300"><strong>smssqlbkup.exe</strong></span>) is doing by switching to it now that we have the address (<span style="color: #993300"><strong>fffffa802935eb10</strong></span>):
<pre class="trace"><span style="font-size: small">5: kd&gt; <strong><span style="color: #0000ff">!mex.p</span> <span style="color: #993300">fffffa802935eb10</span></strong>
Name Address Ses PID User Name Create Time Up Time Mods Handle Act Thrd Z Thrd Parent
============== ================ === ============ =============== ========================== ============ ==== ====== ======== ====== ========================
<span style="color: #993300"><strong>smssqlbkup.exe</strong></span> fffffa802935eb10 0 614 (0n1556) DOMAIN\COMPUTERNAME$ 06/26/2017 12:13:00.723 PM 2h:02:19.276 54 221 8 0 services.exe 264 (0n612)

Command Line: "D:\SMS_FOLDER\bin\x64\smssqlbkup.exe"

Memory Details:

VM Peak Work Set Commit Size PP Quota NPP Quota
======== ========= ======== =========== ========= =========
86.53 MB 107.85 MB 66.95 MB 12.94 MB 137.89 KB 15.38 KB

CPU Details:

User Kernel Total
====== ========= =========
2s.403 2m:21.447 2m:23.850

Show Threads: Unique Stacks !mex.listthreads (!lt) fffffa802935eb10 !winde.lp fffffa802935eb10 !process fffffa802935eb10 7

Show LPC Port information for process</span></pre>
Let's have a look at the list of threads and afterwards we should have a look at each thread - we can do this using <span style="color: #0000ff"><strong>!mex.lt</strong></span> now that we are already in the context of this process:
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.lt</strong></span>
Process PID Thread Id Time Reason
============== === ================ ==== ======= ==============
smssqlbkup.exe 614 fffffa8029361b50 5c0 2s.371 UserRequest
smssqlbkup.exe 614 fffffa801f6a5b50 53c 43s.649 DelayExecution
smssqlbkup.exe 614 <span style="color: #99cc00"><strong>fffffa801f6a55c0</strong> </span>874 514ms Executive
smssqlbkup.exe 614 fffffa80293b2b50 c38 43s.649 UserRequest
smssqlbkup.exe 614 fffffa80295c0b50 7d4 43s.649 UserRequest
smssqlbkup.exe 614 fffffa801f929b50 11fc 43s.649 WrQueue
smssqlbkup.exe 614 fffffa8021324060 1af4 2s.386 WrQueue
smssqlbkup.exe 614 fffffa8029610060 10a0 2s.371 WrQueue

Thread Count: 8</span></pre>
Looking through each thread, we find this veeery interesting thread (<span style="color: #99cc00"><strong>fffffa801f6a55c0</strong></span>):
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.t</strong></span> <span style="color: #99cc00"><strong>fffffa801f6a55c0</strong></span>
Process Thread CID UserTime KernelTime ContextSwitches Wait Reason Time COM-Initialized
smssqlbkup.exe (fffffa802935eb10) fffffa801f6a55c0 614.874 1s.841 2m:21.228 36298 Executive 514ms APTKIND_MULTITHREADED (MTA)

WaitBlockList:
Object Type Other Waiters
fffff880074906d0 NotificationEvent 0

# Child-SP Return Call Site
0 fffff88007490430 fffff80001edd142 nt!KiSwapContext+0x7a
1 fffff88007490570 fffff80001edf96f nt!KiCommitThreadWait+0x1d2
2 fffff88007490600 fffff80001ea2527 <span style="color: #ff00ff"><strong>nt!KeWaitForSingleObject</strong></span>+0x19f
3 fffff880074906a0 fffff880016ebcc8 <span style="color: #ff0000"><strong>nt!CcCanIWrite</strong></span>+0xfffffffffffa11f7
4 fffff88007490770 fffff88001401102 Ntfs!NtfsCopyWriteA+0x68
5 fffff88007490970 fffff880014048ba fltmgr!FltpPerformFastIoCall+0xf2
6 fffff880074909d0 fffff8800142283e fltmgr!FltpPassThroughFastIo+0xda
7 fffff88007490a10 fffff800021f1bbe fltmgr!FltpFastIoWrite+0x1ce
8 fffff88007490ab0 fffff80001ed70d3 <span style="color: #33cccc"><strong>nt!NtWriteFile</strong></span>+0x5ad
9 fffff88007490bb0 0000000077a2bdba nt!KiSystemServiceCopyEnd+0x13
a 00000000014cce38 000007fefd73865c ntdll!NtWriteFile+0xa
b 00000000014cce40 00000000778d171a KERNELBASE!WriteFile+0xfe
c 00000000014cceb0 00000000778d1ea5 kernel32!BaseCopyStream+0x4b2
d 00000000014cd8a0 00000000778d1907 kernel32!BasepCopyFileExW+0x545
e 00000000014cdda0 00000000779556f2 kernel32!CopyFileExW+0x97
f 00000000014cde20 000000013ff6fb4a <span style="color: #33cccc"><strong>kernel32!CopyFileA</strong></span>+0x62
<strong>10 00000000014cde80 000000013ff81a5c smssqlbkup+0x9fb4a
11 00000000014cdf10 000000013ff7c430 smssqlbkup+0xb1a5c
12 00000000014ce280 000000013ff7bb5a smssqlbkup+0xac430
13 00000000014cf3b0 000000013ff7753f smssqlbkup+0xabb5a
14 00000000014cf400 000000013ff7987c smssqlbkup+0xa753f
15 00000000014cf6f0 000000013ff85643 smssqlbkup+0xa987c
16 00000000014cf7c0 0000000140155d55 smssqlbkup+0xb5643
17 00000000014cf9e0 0000000140155bec smssqlbkup+0x285d55
18 00000000014cfa10 00000000778d59cd smssqlbkup+0x285bec</strong>
19 00000000014cfa40 0000000077a0a561 kernel32!BaseThreadInitThunk+0xd
1a 00000000014cfa70 0000000000000000 ntdll!RtlUserThreadStart+0x1d</span></pre>
Well, well, well - what do we have on the stack here?
<ul>
 	<li>first of all we are clearly trying to write to a file (<span style="color: #33cccc"><strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff557714(v=vs.85).aspx">nt!NtWriteFile </a></strong></span>after the usermode call to <a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa363851(v=vs.85).aspx">CopyFile</a> because the <strong>smssqlbkup.exe</strong> process is trying to copy the file)</li>
 	<li>second of all we are waiting in <span style="color: #ff0000"><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff539021(v=vs.85).aspx"><strong>nt!CcCanIWrite</strong></a></span> (remember explanation of throttling from above)</li>
</ul>
So, it seems that we either have a very slow disk or we have a problem with some disk related driver. Let's check for any pending disk <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/gettingstarted/i-o-request-packets">IRPs</a> - we can do this by running <span style="color: #0000ff"><strong>!mex.ioq </strong></span>(you can use <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-irpfind"><strong>!kdexts.irpfind</strong></a>, but will need to parse the results manually):
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.ioq</strong></span>
Collecting Data...This might take a moment.
Collecting Raid Data...Returned Failure
Collecting Disk Data...Added Object Disk with Filter DISK
Returned Success

================== Disk.sys Devices ==========================

Device Name DeviceObject <strong>DeviceExtension</strong> PrivateFdoData <span style="color: #ff0000"><strong>PendingIRPs</strong></span>
===================== ================ ================ ================ ===========
<strong>\Device\Harddisk0\DR0 fffffa801cd28060 <span style="color: #339966">fffffa801cd281b0</span> fffffa801cd29010 <span style="color: #ff0000">2</span></strong>
==================RaidPort Info: \Device\RaidPort2 ==========================
Device Name Miniport DeviceExtension BusType IoModel
=================================== ======== ================ =========== =========================
\Device\RaidPort2(fffffa801a668060) somestoragedriver fffffa801a6681b0 BusTypeRAID StorSynchronizeFullDuplex
RaidUnit(LUN) ClassPNPDevice DeviceState QueueState OutstandingCount QueueDepth PendingIrps
================ ================ ================== ========== ================ ========== ===========
fffffa801a6b2930 fffffa801cd28060 DeviceStateWorking Normal 2 254 2

Summary Notes:
IOQ found 80 devices, of which 2 have a total of 4 pending Irps.</span></pre>
Alright, so we have pending disk IRPs - let's have a look at the IRP queue now that we have the DeviceExtension address (<span style="color: #339966"><strong>fffffa801cd281b0</strong></span>) by using <span style="color: #0000ff"><strong>!mex.ioq</strong></span> again, but this time with the "<span style="color: #0000ff"><strong>-e</strong></span>" parameter with the address (<span style="color: #339966"><strong>fffffa801cd281b0</strong></span>):
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.ioq -e</strong></span> <span style="color: #339966"><strong>fffffa801cd281b0</strong></span>

============================================
Disk Information: <strong>\Device\Harddisk0\DR0</strong>
============================================
ClassPNP Devices(Disk.sys) Information:
============================================
Device Name DeviceObject DeviceExtension PrivateFdoData PendingIRPs
===================== ================ ================ ================ ===========
\Device\Harddisk0\DR0 fffffa801cd28060 fffffa801cd281b0 fffffa801cd29010 2

Transfer Packet <span style="color: #ff00ff"><strong>Current Irp</strong></span> Thread Wait Thread #Retries TimeOut (s) DeviceName CurrentDrvr Original Irp FileName Srb SrbStatus
================ ================ =========== ============================== ======== =========== =============== =========== ================ ============= ================ ==================
<strong>fffffa801d11a310 <span style="color: #ff00ff">fffffa801d11b010</span> 15ms fffffa80213cc430(RAMMap64.exe) 0 0 HarddiskVolume2 somestoragedriver fffffa8029b27010 \<span style="color: #ff6600">pagefile.sys</span> fffffa801d11a430 <span style="color: #ff0000">SRB_STATUS_PENDING</span>
fffffa801d1fdb10 <span style="color: #ff00ff">fffffa801d1fd910</span> 0s fffffa8029573b50(sqlservr.exe) 0 0 HarddiskVolume2 somestoragedriver fffffa801f8ab980 \<span style="color: #ff6600">pagefile.sys</span> fffffa801d1fdc30 <span style="color: #ff0000">SRB_STATUS_PENDING</span></strong></span></pre>
Wow ... stuck IRPs on writing to the page file (<span style="color: #ff6600"><strong>pagefile.sys</strong></span>) - remember that the memory mapped files are usually backed by the page file.

So, now it's clear and it does not matter that that we do not see our file here - this is normal because at the time the dump was taken, the we were waiting in <span style="color: #ff0000"><a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/hardware/ff539021(v=vs.85).aspx"><strong>nt!CcCanIWrite</strong></a></span> and it seems that we did not have any pending IRP for it currently.

The important thing is that we have a disk related issue here.

Let's have a quick look at both IRPs in more detail by using <span style="color: #0000ff"><strong>!mex.mirp</strong></span> with the "<span style="color: #0000ff"><strong>-v</strong></span>" parameter (for verbose) and each IRP addresses (<span style="color: #ff00ff"><strong>fffffa801d11b010</strong> </span>&amp; <span style="color: #ff00ff"><strong>fffffa801d1fd910</strong></span>) (you can use <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-irp"><strong>!kdexts.irp</strong></a> instead):
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.mirp -v</strong></span> <span style="color: #ff00ff"><strong>fffffa801d11b010</strong></span>

Irp Details: fffffa801d11b010 [ verbose | !ddt | !winde.io | !irp ]

Mdl : fffffa801fd8a7b0
System buffer :
Issuing Process :
Thread :
Frame Count : 2
IoStatus Status : c00000bb
IoStatus Info : 0000000000000000
Requester Mode :
Cancel : 0
Cancel IRQL : 0
Apc Environment : 0
User Iosb : 0000000000000000
User Event :
APC : 0000000000000000
Completion Key : 0000000000000000
Cancel Routine :
Original File Object: 0000000000000000
Original File Name :

Irp Stack Frame(s)

# <span style="color: #ff0000"><strong>Driver</strong> </span>Major Minor Dispatch Routine Control Code Flg Ctrl Status Completion Invoker(s) Device QueueLocation File Context Completion Routine Args
=== ================ ======================= ===== ======================== ============ === ==== ======= ====================== ================ ============= ====== ====================== ============================ ===============================================================================
1 CREATE 0 0 0 None 0000000000000000 (null) 0000000000000000 0000000000000000 0000000000000000 0000000000000000
-&gt;2 \Driver\<span style="color: #ff0000"><strong>somestoragedriver</strong> </span>INTERNAL_DEVICE_CONTROL 0 storport!RaDriverScsiIrp 12 e1 Pending Cancel, Success, Error fffffa801a6b27e0 (null) fffffa801d11a310(CPnp) CLASSPNP!TransferPktComplete fffffa801d11a430(CPnp) 0000000000000000 0000000000000000 fffffa801a6b2930(Devi)

<span style="color: #ff0000"><strong>IO Status: 0xc00000bb (The request is not supported.)</strong></span>

 

5: kd&gt; <span style="color: #0000ff"><strong>!mex.mirp -v</strong></span> <span style="color: #ff00ff"><strong>fffffa801d1fd910</strong></span>

Irp Details: fffffa801d1fd910 [ verbose | !ddt | !winde.io | !irp ]

Mdl : fffffa801f5b9670
System buffer :
Issuing Process :
Thread :
Frame Count : 2
IoStatus Status : c00000bb
IoStatus Info : 0000000000000000
Requester Mode :
Cancel : 0
Cancel IRQL : 0
Apc Environment : 0
User Iosb : 0000000000000000
User Event :
APC : 0000000000000000
Completion Key : 0000000000000000
Cancel Routine :
Original File Object: 0000000000000000
Original File Name :

Irp Stack Frame(s)

# <span style="color: #ff0000"><strong>Driver</strong> </span>Major Minor Dispatch Routine Control Code Flg Ctrl Status Completion Invoker(s) Device QueueLocation File Context Completion Routine Args
=== ================ ======================= ===== ======================== ============ === ==== ======= ====================== ================ ============= ====== ====================== ============================ ===============================================================================
1 CREATE 0 0 0 None 0000000000000000 (null) 0000000000000000 0000000000000000 0000000000000000 0000000000000000
-&gt;2 \Driver\<span style="color: #ff0000"><strong>somestoragedriver</strong> </span>INTERNAL_DEVICE_CONTROL 0 storport!RaDriverScsiIrp 12 e1 Pending Cancel, Success, Error fffffa801a6b27e0 (null) fffffa801d1fdb10(CPnp) CLASSPNP!TransferPktComplete fffffa801d1fdc30(CPnp) 0000000000000000 0000000000000000 fffffa801a6b2930(Devi)

<span style="color: #ff0000"><strong>IO Status: 0xc00000bb (The request is not supported.)</strong></span></span></pre>
Ok, there we go, we are stuck with these IRPs inside of the disk vendor driver (called "<span style="color: #ff0000"><strong>somestoragedriver</strong></span>" here for obvious purposes). The cause these are stuck is that we get the IO Status <span><span style="color: #ff0000"><strong>0xc00000bb</strong> </span>from the <a target="_blank" href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa363219(v=vs.85).aspx">IOCTL</a>, which means <span style="color: #ff0000"><strong>STATUS_NOT_SUPPORTED</strong></span> (<span style="color: #ff0000"><em>The request is not supported</em></span>).</span>

Last thing - let's check some information about this driver (like how old it is) - we can do this by running <span style="color: #0000ff"><strong>lmtm</strong> </span>(<em>or any other <span style="color: #0000ff"><strong>lm*</strong></span> command</em>) and give it the name of the driver (<strong>somestoragedriver</strong>):
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>lmtm</strong> </span><span style="color: #ff0000"><strong>somestoragedriver</strong></span>
Browse full module list
start end module name
fffff880`01549000 fffff880`01559000 <span style="color: #ff0000"><strong>somestoragedriver</strong> </span>Mon <span style="color: #ff0000"><strong>Aug 9 21:21:24 2010</strong></span> (4C604724)</span></pre>
Wow ... this is awesome ... we are in <strong>July 2017</strong> and this disk driver is from <span style="color: #ff0000"><strong>August 2010</strong></span> ... niiice ...

&nbsp;

So, what we need to do is:
<ul>
 	<li>Update the "<span style="color: #ff0000"><strong>somestoragedriver.sys</strong></span>" driver to the latest existing version</li>
 	<li>After this, monitor disk performance using <a target="_blank" href="https://blogs.technet.microsoft.com/askcore/2012/03/16/windows-performance-monitor-disk-counters-explained/">Performance Monitor</a> and check if the disk is performing well</li>
</ul>
Sure enough, after updating <span>the "</span><span style="color: #ff0000"><strong>somestoragedriver.sys</strong></span><span>" driver, the issue was solved and the SCCM server stopped eating up memory until it gets into a hung state.</span>

&nbsp;

WOOT! :D

&nbsp;

<span style="color: #339966"><strong>PS:</strong></span> We can also get to the file directly by running <span style="color: #0000ff"><strong>!mex.mem -p</strong></span>, but this command usually takes a very long time (couple of hours sometimes, depending how big the dump is - this can also be achieved with <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-memusage"><span style="color: #ff6600"><strong>!kdexts.memusage</strong></span></a>, but the output will need to be looked at manually - not summary for the <strong><em>Mapped Files</em></strong>).

The reason why it takes a lot of time, is that it has to scan the <a target="_blank" href="https://social.technet.microsoft.com/wiki/contents/articles/15259.page-frame-number-pfn-database.aspx"><strong>PFN</strong> (Page Frame Number)</a> database and process all the data.
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #0000ff"><strong>!mex.mem -p</strong></span>
<strong>Loading PFN database... Building kernel map...this will take a while.</strong>

Top physical RAM users:

Type Name <strong>ControlArea</strong>/PID Valid Standby <strong>Dirty</strong> Shared Locked PageTables TOTAL
=========== ============== ================ ========= ======== ======== ======= ========= ========== =========
<span style="color: #ff6600"><strong>Mapped File</strong></span> <span style="color: #ff0000"><strong>CM_123.mdf</strong></span> <strong>FFFFFA80204FFD30</strong> 10.69 MB <span style="color: #ff0000"><strong>15.54 GB</strong></span> 15.55 GB
Process sqlservr.exe 14866272 14.18 GB 79.96 MB 16 KB n/a n/a 35.34 MB 14.29 GB
Process ReportingServi FFFFFA80292A6B10 241.43 MB 2.62 MB 16 KB n/a n/a 2.28 MB 246.35 MB
System NonPaged Pool 184.33 MB n/a 184.33 MB 184.33 MB
Process RAMMap64.exe FFFFFA8020C87380 111.77 MB 4.94 MB n/a n/a 2.06 MB 118.77 MB
Process some_other_process FFFFFA8029411060 97.23 MB 1.47 MB n/a n/a 1.18 MB 99.88 MB
System Kernel Stacks 53.94 MB 44 KB n/a 992 KB 128 KB 54.11 MB
Process procexp64.exe FFFFFA80297EB060 36.13 MB n/a n/a 608 KB 36.72 MB
Process svchost.exe FFFFFA8028EF25D0 28.81 MB 1.97 MB n/a n/a 732 KB 31.49 MB
Process explorer.exe FFFFFA8029673A40 23.09 MB 196 KB n/a n/a 724 KB 23.99 MB
Process perfmon.exe FFFFFA802976A6C0 21.61 MB 160 KB n/a n/a 460 KB 22.21 MB
Mapped File sqlservr.exe FFFFFA8029838AC0 20.22 MB 20.22 MB
Process explorer.exe FFFFFA80296AAB10 19.06 MB 120 KB n/a n/a 664 KB 19.82 MB
Process lsass.exe FFFFFA801F106A70 18.47 MB 96 KB n/a n/a 352 KB 18.91 MB
Process WmiPrvSE.exe FFFFFA80294AF060 18.11 MB 4 KB n/a n/a 548 KB 18.64 MB
Process smsexec.exe FFFFFA801F5D0B10 17.64 MB 40 KB n/a n/a 724 KB 18.38 MB
Process procexp64.exe FFFFFA802A574B10 17.18 MB 40 KB n/a n/a 460 KB 17.66 MB
Mapped File shell32.dll FFFFFA801EF80680 13.5 MB 3.12 MB 16.62 MB
Process svchost.exe FFFFFA8028F0BB10 15.03 MB 28 KB n/a n/a 432 KB 15.48 MB
Process some_process FFFFFA8029018B10 14.19 MB 196 KB n/a n/a 432 KB 14.8 MB
=========== ============== ================ ========= ======== ======== ======= ========= ========== =========
Type Name ControlArea/PID Valid Standby Dirty Shared Locked PageTables TOTAL

Only the top 20 of 1612 rows are being shown. Show all

Virtual Memory Physical Memory File Cache Cache Writes</span></pre>
&nbsp;

Here is how it would look like with <a target="_blank" href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/-memusage"><span style="color: #ff6600"><strong>!kdexts.memusage</strong></span></a> with all other stuff snipped out:
<pre class="trace"><span style="font-size: small">5: kd&gt; <span style="color: #ff6600"><strong>!kdexts.memusage</strong></span>
<em>[...SNIPPED...]</em>
Usage Summary (<strong>in Kb</strong>):
<strong>Control</strong> Valid Standby <span style="color: #ff0000"><strong>Dirty</strong> </span>Shared Locked PageTables name
ffffffffffffd 8384 0 0 0 0 0 AWE
fffffa8019a34010 440 0 0 184 0 0 mapped_file( winhttp.dll )
fffffa8019ac18d0 16 0 0 0 0 0 mapped_file( netutils.dll )
<em>[...SNIPPED...]</em>
<strong>fffffa80204ffd30</strong> 10944 0 <span style="color: #ff0000"><strong>16292096</strong> </span>0 0 0 <span style="color: #ff6600"><strong>mapped_file</strong></span>( <span style="color: #ff0000"><strong>CM_123.mdf</strong></span> )
<em>[...SNIPPED...]</em></span></pre>
&nbsp;

Don't forget to read-up on your <strong><a target="_blank" href="https://technet.microsoft.com/en-us/sysinternals/bb963901.aspx">Windows Internals</a></strong> ;)

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>Transforming Incidents to other WorkItem types via Console Tasks in Service Manager (SCSM Dev custom Solutions)</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/transforming-incidents-to-other-workitem-types-via-console-tasks-in-service-manager-scsm-dev-custom-solutions</link>
      <pubDate>Mon, 24 Oct 2016 22:31:24 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/?p=705</guid>
      <description><![CDATA[The entire solution (source code) is available...]]></description>
      <content:encoded><![CDATA[<span>The entire solution (source code) is available here: </span><strong><a target="_blank" href="https://github.com/SubZer0MS/TransformWorkItemTasks">https://github.com/SubZer0MS/TransformWorkItemTasks</a></strong>

I have been asked to create a solution for Service Manager 2012 R2 that contains Console Tasks that allow users us to transform an Incident into a different WorkItem type. In this example, we are going to have 4 Console Tasks, for each of the other 4 WorkItem types beside Incident (<strong><em>Service Request</em></strong>, <strong><em>Change Request</em></strong>, <strong><em>Release Record</em></strong>, <strong><em>Problem</em></strong>). This way, we can assign permissions only to some or only for the one needed for a specific role like (ex. custom - derived from <strong>Service Request Analyst</strong> role).

This is a pretty nifty example that shows how such a thing can be done and that can be directly used, or stand as a base solution that can be changed or extended as needed :D

This solution will do the following (based on the Task being executed) - example for Service Request (<span>"</span><strong>Transform to SR</strong><span>" Task):</span>
<ol>
 	<li>Create a new Service Request using the Default Service Request Template (uses the default/standard Template for each WorkItem type)</li>
 	<li>Add the Title &amp; Description of the Incident to the Service Request</li>
 	<li>Add the common WorkItem relationships to the Service Request &amp; delete these relationships from the Incident (less data in DB, better performance)</li>
 	<li>Add the Incident to the Service Request as related WorkItem (WorkItemRelatesToWorkItem)</li>
 	<li>Create a new AnalystCommentLog and add it to the Incident as a related AnalystCommentLog containing a comment that the Incident was closed by this transform Task and also containing the new Service Request ID</li>
 	<li>Close the Incident (set the Status to Closed)</li>
</ol>
As for permissions needed, it either needs to be run by users of the <strong>Advanced Operators</strong> role, or this can be configured granular and would need the following permissions:
<ul>
 	<li>close Incidents and add comment on closing (setting Status to Closed, creating AnalystCommentLog and adding it to the Incident as related AnalystCommentLog)</li>
 	<li>creating and editing the WorkItem of the specific Task being executed (ex. if the "<strong>Transform to SR</strong>" is being called for example, then Create/Edit permissions are needed for Service Requests)</li>
</ul>
&nbsp;

The Management Pack Bundle that contains the solution and can be directly imported into Service Manager 2012 R2 is here: <strong><a target="_blank" href="https://msdnshared.blob.core.windows.net/media/2016/11/TransformWorkItemTasks.zip">TransformWorkItemTasks.mpb (zip)</a></strong>

The entire solution (source code) is available here: <strong><a target="_blank" href="https://github.com/SubZer0MS/TransformWorkItemTasks">https://github.com/SubZer0MS/TransformWorkItemTasks</a></strong>

&nbsp;

Let's take a little tour on this with an example of one of the Tasks (let's continue with the <span>"</span><strong>Transform to SR</strong><span>" Task as I have been using it as example up to this point anyway</span>).

All the needed references are already included in the solution folders, so no need to copy/add any DLLs or MPs that are referenced. It is however, a good thing to look at, in order to see what references are being used.

This is how a new Console Task should be declared (under <strong>&lt;Presentation&gt;</strong> node, under <em><strong>&lt;ConsoleTasks&gt;</strong></em>):
<pre class="trace"><span style="font-size: small">&lt;ConsoleTask <strong>ID</strong>="<span style="color: #ff6600"><strong>TransformIncidentToServiceRequest</strong></span>" Accessibility="Public" Enabled="true" <strong>Target</strong>="Incident!<span style="color: #339966"><strong>System.WorkItem.Incident</strong></span>" RequireOutput="false"&gt;
  &lt;Assembly&gt;Console!<em><strong>SdkDataAccessAssembly</strong></em>&lt;/Assembly&gt;
  &lt;Handler&gt;<strong>Microsoft.EnterpriseManagement.UI.SdkDataAccess.ConsoleTaskHandler</strong>&lt;/Handler&gt;
  &lt;Parameters&gt;
    &lt;Argument Name="<strong>Assembly</strong>"&gt;<span style="color: #0000ff"><strong>CustomTransformWorkItemTasks</strong></span>&lt;/Argument&gt;
    &lt;Argument Name="<strong>Type</strong>"&gt;<strong><span style="color: #0000ff">CustomTransformWorkItemTasks</span>.<span style="color: #ff00ff">TransformTaskHandler</span></strong>&lt;/Argument&gt;
    &lt;Argument&gt;<span style="color: #00ff00"><strong>Service</strong></span>&lt;/Argument&gt;
  &lt;/Parameters&gt;
&lt;/ConsoleTask&gt;</span></pre>
By setting the <strong>Target</strong> to <span style="font-size: small"><span style="color: #339966"><strong>System.WorkItem.Incident</strong></span></span>, we tell SM to display this Task in views where we are displaying Incidents (when selecting an Incident).

We are declaring that the Task Handler will be the default <span style="font-size: small"><strong>Microsoft.EnterpriseManagement.UI.SdkDataAccess.ConsoleTaskHandler</strong></span>, and we are passing 3 arguments to this Method:
<ol>
 	<li><strong>Assembly</strong> (needed named argument that allows the Handler to know what DLL it needs to use for this): <span style="color: #0000ff"><strong>CustomTransformWorkItemTasks</strong></span></li>
 	<li><strong>Type</strong> (needed named argument that tells the Handler which is the class from our DLL that is handling this): <strong><span style="color: #0000ff">CustomTransformWorkItemTasks</span>.<span style="color: #ff00ff">TransformTaskHandler</span></strong></li>
 	<li>A 3rd unnamed argument, which is actually the 1st argument that we are passing to our method (<strong><span style="color: #0000ff">CustomTransformWorkItemTasks</span>.<span style="color: #ff00ff">TransformTaskHandler</span></strong>) which is a simple string for which we are manually checking if it is set in our method: <span style="color: #00ff00"><strong>Service</strong></span></li>
</ol>
In the DLL we are developing for this, we are defining our Handler like this:
<ul>
 	<li>note that the (main) namespace is called <span style="color: #0000ff"><strong>CustomTransformWorkItemTasks </strong></span>like our DLL will be called as well</li>
 	<li>also notice, that we define a class in this namespace called <span style="color: #ff00ff"><strong>TransformTaskHandler</strong> </span>that extends the (SM build-in <em>Microsoft.EnterpriseManagement.UI.SdkDataAccess.</em><span style="color: #993366"><strong>ConsoleCommand </strong></span>class)</li>
</ul>
<pre class="trace"><span style="font-size: small">namespace <span style="color: #0000ff"><strong>CustomTransformWorkItemTasks</strong></span>
{
    public class <span style="color: #ff00ff"><strong>TransformTaskHandler</strong> </span>: <span style="color: #993366"><strong>ConsoleCommand</strong></span>
    {</span></pre>
The build-in method <span style="color: #808000"><strong>ExecuteCommand</strong></span> of the <span style="color: #993366"><strong>ConsoleCommand</strong></span> class from which we are inheriting from, which will get executed on initialization, is called , so we have to define that in our class and handle the arguments (in this example the only one argument with the value: <span style="color: #00ff00"><strong>Service</strong></span>) we pass from the MP there:
<pre class="trace"><span style="font-size: small">public override void <span style="color: #808000"><strong>ExecuteCommand</strong></span>(<strong>IList</strong> <span style="color: #000080"><strong>nodes</strong></span>, <strong>NavigationModelNodeTask</strong> task, <strong>ICollection</strong> <span style="color: #ff6600"><strong>parameters</strong></span>)
{</span></pre>
In this method, we decide what we do based on what argument we have sent from the Task (in the MP) - in this case we only pass the argument <span style="color: #00ff00"><strong>Service</strong></span>:
<pre class="trace"><span style="font-size: small">if (<span style="color: #ff6600"><strong>parameters</strong></span>.Contains("<span style="color: #00ff00"><strong>Service</strong></span>"))
{
    <span style="color: #99cc00"><strong><em>// do stuff here - the actual work you need to be done in your task when this argument is passed by the Task</em></strong></span>
    <span style="color: #99cc00"><strong><em>// in this case, I am setting some variables that decide what I will create later in the actual processing based on the WorkItem type (check the entire source code on GitHub)</em></strong></span>
}</span></pre>
This is the part does the actual magic. Notice the <strong>foreach</strong> block, we are going through all the selected <strong><em>Incidents</em> </strong>here, that were selected when running the Task in the Console by enumerating through the <span style="color: #000080"><strong>nodes</strong> </span>list passed as argument to the <span style="color: #808000"><strong>ExecuteCommand</strong> </span>method:
<ul>
 	<li>notice that we are using <span style="color: #0000ff"><strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/gg461780.aspx">EnterpriseManagementObjectProjection</a></strong></span> with Class Type constructor in order to be able to create Class &amp; Relationship objects together</li>
 	<li>we are just adding the Relationships we create to the class object, by adding it to the <span style="color: #0000ff"><strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/gg461780.aspx">EnterpriseManagementObjectProjection</a></strong></span> class using the <span style="color: #800000"><strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/gg458569.aspx">Add(...)</a></strong></span> Method</li>
 	<li>in order to "really" save/create the Class &amp; Relationship objects of this projection into the CMDB, which we are currently only having in memory, we now need to call <span style="color: #008000"><a target="_blank" href="https://msdn.microsoft.com/en-us/library/gg460543.aspx"><strong>Overwrite()</strong></a></span> Method on the projection</li>
 	<li>when we create the <strong>AnalystCommentLog</strong>, we are using <span style="color: #cc99ff"><strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/gg461732.aspx">CreatableEnterpriseManagementObject</a></strong></span> because it's an object that does not exist yet and we are just creating it, but we don't need to use a projection (<span style="color: #0000ff"><strong><a target="_blank" href="https://msdn.microsoft.com/en-us/library/gg461780.aspx">EnterpriseManagementObjectProjection</a></strong></span>) because we will not create &amp; add any Relationship to it (we are just adding the newly object itself as a related object to the new Service Request)</li>
 	<li>we need to make sure to set the correct Status for the new WorkItem in order for the internal workflows to correctly process it in order for it to get in progress (Status will be New or Active depending on the WorkItem type)</li>
 	<li>it is also very important to set the Prefixes for each Activity (depending on the type) that exists in the WorkItem Template we apply (which in this case is the default Template for each WorkItem type)</li>
 	<li>another special case we need to worry about, is when we are cloning the Relationships - if the RelationshipType is derived from <strong>System.Membership</strong>, it is very important to create a brand new Target object copied from the existing one (new <strong><em>BaseManagedEntityId</em></strong>) because Relationships of this type (Membership) have a Target object which is bound to it's source (<em>it cannot have a Relationship to 2 different objects</em>)</li>
 	<li>all the MP, Class, etc. names are defined in a separate CS file called <span style="color: #ff6600"><em><strong>Constants</strong> </em></span>when different classes are defined - check the actual source code on GitHub to understand those</li>
 	<li><strong>check the comments for more detailed explanations</strong></li>
</ul>
<pre class="trace"><span style="font-size: small"><span style="color: #339966"><strong>// here is the code that does the actual work
// we wrap this around a try/catch block to handle any exception that may happen and display it in case of failure</strong></span>

try
{
    <span style="color: #339966"><strong>// getting the types we need based on the string variables we have filled earlier based on the WorkItem type we need to create</strong></span>

    ManagementPack workItemMp = emg.GetManagementPack(workItemMpName, Constants.mpKeyTocken, Constants.mpSMR2Version);
    ManagementPack mpSettings = emg.GetManagementPack(workItemSettingMpName, Constants.mpKeyTocken, Constants.mpSMR2Version);
    ManagementPack knowledgeLibraryMp = emg.GetManagementPack(ManagementPacks.knowledgeLibrary, Constants.mpKeyTocken, Constants.mpSMR2Version);

    ManagementPackClass workItemClass = emg.EntityTypes.GetClass(workItemClassName, workItemMp);
    ManagementPackClass workItemClassSetting = emg.EntityTypes.GetClass(workItemSettingClassName, mpSettings);

    EnterpriseManagementObject generalSetting = emg.EntityObjects.GetObject&lt;EnterpriseManagementObject&gt;(workItemClassSetting.Id, ObjectQueryOptions.Default);

    <span style="color: #339966"><strong>// here is the foreach loop that processes each class-object (in this case Incident) that was multi-selected in the view before executing the Task</strong></span>

    foreach (NavigationModelNodeBase node in nodes)
    {
        <span style="color: #339966"><strong>// we need to setup an IList which contains only 1 GUID that correspons to the Incident we are currently working on (node["Id"])
        // this is needed because we are using the IObjectProjectionReader.GetData(...) which gets an IList&lt;Guid&gt; as parameter in order to retreive the class-objects we want from the db</strong></span>

        IList&lt;Guid&gt; bmeIdsList = new List&lt;Guid&gt;();
        bmeIdsList.Add(new Guid(node[Constants.nodePropertyId].ToString()));

        <span style="color: #339966"><strong>// we are setting up the ObjectProjectionCriteria using the "System.WorkItem.Incident.ProjectionType" Type Projection as we need to get all the Relationships of the Incident
        // we will use ObjectRetrievalOptions.Buffered so that we don't get any data from the db which we don't need - we will only get the data one we call the IObjectProjectionReader.GetData(...) method
        // we are getting the data reader object using GetObjectProjectionReader(...) and setting its PageSize to 1 because we only need 1 object retrieved here</strong></span>

        ObjectProjectionCriteria incidentObjectProjection = new ObjectProjectionCriteria(incidentProjection);
        ObjectQueryOptions queryOptions = new ObjectQueryOptions(ObjectPropertyRetrievalBehavior.All);
        queryOptions.ObjectRetrievalMode = ObjectRetrievalOptions.Buffered;
        IObjectProjectionReader&lt;EnterpriseManagementObject&gt; incidentReader = emg.EntityObjects.GetObjectProjectionReader&lt;EnterpriseManagementObject&gt;(incidentObjectProjection, queryOptions);
        incidentReader.PageSize = 1;

        <span style="color: #339966"><strong>// we are using EnterpriseManagementObjectProjection for the Incident we are getting from the db instead of EnterpriseManagementObject
        // this is because we are getting a (Type) Projection object (class-object together with its Relationships &amp; relationship class-objects</strong></span>

        EnterpriseManagementObjectProjection incident = incidentReader.GetData(bmeIdsList).FirstOrDefault();

        <span style="color: #339966"><strong>// we are doing the same for the new WorkItem class-object we are creating because we want to add Relationships (with their relationship class-objects from the Incident) here as well
        // if we would only have created the new WorkItem class and nothing else with it (no Relationships), we could have used the CreatableEnterpriseManagementObject class (which needs to be used when a new class-object is getting created)</strong></span>

        EnterpriseManagementObjectProjection workItem = new EnterpriseManagementObjectProjection(emg, workItemClass);

        <span style="color: #339966"><strong>// now we need to assign some Template to the new WorkItem (if a default/standard Template exists) in order to already have some Activities created
        // the Activities and all other Properties of the new WorkItem can be adjusted by modifying the default/standard Template for each WorkItem type</strong></span>

        if (!string.IsNullOrEmpty(workItemTemplateName))
        {
            ManagementPackObjectTemplateCriteria templateCriteria = new ManagementPackObjectTemplateCriteria(string.Format("Name = '{0}'", workItemTemplateName));
            ManagementPackObjectTemplate template = emg.Templates.GetObjectTemplates(templateCriteria).FirstOrDefault();

            if(template != null)
            {
                <span style="color: #339966"><strong>// if a Template with this name exists, we apply it to the new WorkItem by calling ApplyTemplate(...) on it</strong></span>

                workItem.ApplyTemplate(template);

                <span style="color: #339966"><strong>// if we have a Template, we also need to process each Activity that it contains in order to set the Prefix for each Activity (based on its type)
                // we are using the activityPrefixMapping variable we defined above in oder to map each Prefix based on each Activity class-type</strong></span>

                ManagementPack activityManagementMp = emg.GetManagementPack(ManagementPacks.activityManagementLibrary, Constants.mpKeyTocken, Constants.mpSMR2Version);
                ManagementPackRelationship workItemContainsActivityRelationshipClass = emg.EntityTypes.GetRelationshipClass(RelationshipTypes.workItemContainsActivity, activityLibMp);
                ManagementPackClass activitySettingsClass = emg.EntityTypes.GetClass(ClassTypes.activitySettings, activityManagementMp);

                EnterpriseManagementObject activitySettings = emg.EntityObjects.GetObject&lt;EnterpriseManagementObject&gt;(activitySettingsClass.Id, ObjectQueryOptions.Default);

                <span style="color: #339966"><strong>// for each Activity that exists in the Template we applied, we are going to get its Prefix setting and apply it to its ID in the format: "PREFIX{0}"
                // "{0}" is the string pattern we need to set for any new WorkItem (including Activity) class-object we are creating as this will be replaced by the next ID available for the new WorkItem</strong></span>

                foreach (IComposableProjection activity in workItem[workItemContainsActivityRelationshipClass.Target])
                {
                    ManagementPackClass activityClass = activity.Object.GetClasses(BaseClassTraversalDepth.None).FirstOrDefault();
                    string prefix = activitySettings[null, activityPrefixMapping[activityClass.Name]].Value as string;
                    activity.Object[null, ActivityProperties.Id].Value = string.Format("{0}{1}", prefix, Constants.workItemPrefixPattern);
                }
            }
        }

        <span style="color: #339966"><strong>// we are setting the Properties for the new WorkItem class-object here from some Properties of the inital Incident (add more as needed)
        // it is of highest importance that we also set its status to New/Active (depending on WorkItem class-type) in order for it to be properly processed by the internal workflows on creation
        // if we don't set the the correct "creation" Status here, it will never be able to progress into a working state and will remain stuck in a "pending" state</strong></span>

        ManagementPackEnumerationCriteria workItemStatusNewEnumCriteria = new ManagementPackEnumerationCriteria(string.Format("Name = '{0}'", workItemStatusName));
        ManagementPackEnumeration workItemStatusNew = emg.EntityTypes.GetEnumerations(workItemStatusNewEnumCriteria).FirstOrDefault();

        workItem.Object[workItemClass, WorkItemProperties.Id].Value = string.Format("{0}{1}", generalSetting[workItemClassSetting, workItemSettingPrefixName], Constants.workItemPrefixPattern);
        workItem.Object[workItemClass, WorkItemProperties.Title].Value = string.Format("{0} ({1})", incident.Object[incidentClass, WorkItemProperties.Title].Value, incident.Object[incidentClass, WorkItemProperties.Id].Value);
        workItem.Object[workItemClass, WorkItemProperties.Description].Value = incident.Object[incidentClass, WorkItemProperties.Description].Value;
        workItem.Object[workItemClass, WorkItemProperties.Status].Value = workItemStatusNew.Id;

        <span style="color: #339966"><strong>// due to the fact that the Problem WorkItem does not have any Template we can use to create it, we need to handle this special case
        // we need to populate all the required fields when creating the Problem WorkItem, or creating it will fail (Urgency, Impact, Category)</strong></span>

        if (!string.IsNullOrEmpty(workItemUrgencyName))
        {
            ManagementPackEnumerationCriteria workItemUrgencyEnumCriteria = new ManagementPackEnumerationCriteria(string.Format("Name = '{0}'", workItemUrgencyName));
            ManagementPackEnumeration workItemUrgency = emg.EntityTypes.GetEnumerations(workItemUrgencyEnumCriteria).FirstOrDefault();
            workItem.Object[workItemClass, WorkItemProperties.Urgency].Value = workItemUrgency.Id;
        }

        if (!string.IsNullOrEmpty(workItemImpactName))
        {
            ManagementPackEnumerationCriteria workItemImpactEnumCriteria = new ManagementPackEnumerationCriteria(string.Format("Name = '{0}'", workItemImpactName));
            ManagementPackEnumeration workItemImpact = emg.EntityTypes.GetEnumerations(workItemImpactEnumCriteria).FirstOrDefault();
            workItem.Object[workItemClass, WorkItemProperties.Impact].Value = workItemImpact.Id;
        }

        if (!string.IsNullOrEmpty(workItemCategoryName))
        {
            ManagementPackEnumerationCriteria workItemCategoryEnumCriteria = new ManagementPackEnumerationCriteria(string.Format("Name = '{0}'", workItemCategoryName));
            ManagementPackEnumeration workItemCategory = emg.EntityTypes.GetEnumerations(workItemCategoryEnumCriteria).FirstOrDefault();
            workItem.Object[workItemClass, WorkItemProperties.Category].Value = workItemCategory.Id;
        }

        <span style="color: #339966"><strong>// we are adding the initial Incident to this new WorkItem as related WorkItem (System.WorkItemRelatesToWorkItem)</strong></span>

        ManagementPackRelationship workItemToWorkItemRelationshipClass = emg.EntityTypes.GetRelationshipClass(RelationshipTypes.workItemRelatesToWorkItem, wiLibraryMp);
        workItem.Add(incident.Object, workItemToWorkItemRelationshipClass.Target);

        <span style="color: #339966"><strong>// we are closing the current Incident by setting its Status to Closed and setting a closed date</strong></span>

        incident.Object[incidentClass, IncidentProperties.Status].Value = incidentClosedStatus.Id;
        incident.Object[incidentClass, IncidentProperties.ClosedDate].Value = DateTime.Now.ToUniversalTime();

        <span style="color: #339966"><strong>// we create a new (analyst) comment (System.WorkItem.TroubleTicket.AnalystCommentLog) and we add it to the Incident in oder to comment the fact that it was closed tue to this WorkItem Transfomr Task</strong></span>

        CreatableEnterpriseManagementObject analystComment = new CreatableEnterpriseManagementObject(emg, analystCommentClass);
        analystComment[analystCommentClass, AnalystCommentProperties.Id].Value = Guid.NewGuid().ToString();
        analystComment[analystCommentClass, AnalystCommentProperties.Comment].Value = string.Format(Constants.incidentClosedComment, workItemClass.Name, workItem.Object.Id.ToString());
        analystComment[analystCommentClass, AnalystCommentProperties.EnteredBy].Value = EnterpriseManagementGroup.CurrentUserName;
        analystComment[analystCommentClass, AnalystCommentProperties.EnteredDate].Value = DateTime.Now.ToUniversalTime();

        ManagementPackRelationship incidentHasAnalystCommentRelationshipClass = emg.EntityTypes.GetRelationshipClass(RelationshipTypes.workItemHasAnalystComment, wiLibraryMp);
        incident.Add(analystComment, incidentHasAnalystCommentRelationshipClass.Target);

        <span style="color: #339966"><strong>// we create an IList of RelationshipTypes we want to transfer from the Incident to the new WorkItem
        // this is the place we can add any new/custom RelationshipTypes which we want to transfer
        // just make sure that the RelationshipType can be transfered from an Incident to any other WorkItem class-type</strong></span>

        IList&lt;ManagementPackRelationship&gt; relationshipsToAddList = new List&lt;ManagementPackRelationship&gt;()
        {
            workItemToWorkItemRelationshipClass,
            emg.EntityTypes.GetRelationshipClass(RelationshipTypes.createdByUser, wiLibraryMp),
            emg.EntityTypes.GetRelationshipClass(RelationshipTypes.affectedUser, wiLibraryMp),
            emg.EntityTypes.GetRelationshipClass(RelationshipTypes.assignedToUser, wiLibraryMp),
            emg.EntityTypes.GetRelationshipClass(RelationshipTypes.workItemHasAttachment, wiLibraryMp),
            emg.EntityTypes.GetRelationshipClass(RelationshipTypes.workItemAboutConfigItem, wiLibraryMp),
            emg.EntityTypes.GetRelationshipClass(RelationshipTypes.workItemRelatesToConfigItem, wiLibraryMp),
            emg.EntityTypes.GetRelationshipClass(RelationshipTypes.entityToArticle, knowledgeLibraryMp),
            emg.EntityTypes.GetRelationshipClass(RelationshipTypes.workItemHasCommentLog, wiLibraryMp),
        };

        <span style="color: #339966"><strong>// we are getting an instance of the "System.Membership" RelationshipType as we need to handle RelationshipTypes derived from it as a special case
        // the reason for this, is that Target class-objects of the "System.Membership" RelationshipType are bound to their Source class-objects
        // being bound, means that Target class-objects of membership relationships cannot belong to 2 different (Source) class-objects
        // because of this, we need to make a copy (using "CreatableEnterpriseManagementObject" to create a new object and copying the Properties) of the existing Target class-object
        // and add that to the new WorkItem instead of adding the already existing Target class-object</strong></span>

        ManagementPack systemLibraryMp = emg.GetManagementPack(ManagementPacks.systemLibrary, Constants.mpKeyTocken, Constants.mpSMR2Version);
        ManagementPackRelationship membershipRelationshipClass = emg.EntityTypes.GetRelationshipClass(RelationshipTypes.membership, systemLibraryMp);

        <span style="color: #339966"><strong>// we are going through each Target &amp; Source Relationships of the Incident as defined in the relationshipsToAddList variable and adding them to the new WorkItem
        // we are handling the Target RelationshipTypes which are derived from "System.Membership" as a special case as explained above
        // notice that we are also removing these Relationships from the Incident by calling Remove()
        // we are removing the Relationships from the Incident for performance purposes - in order to have less Relationships (less data) in the db
        // comment the "itemProjection.Remove();" in order to keep the Relationships to the Incident as well if needed for some reason</strong></span>

        foreach (ManagementPackRelationship relationship in relationshipsToAddList)
        {
            if (incident[relationship.Target].Any())
            {
                foreach (IComposableProjection itemProjection in incident[relationship.Target])
                {
                    <span style="color: #339966"><strong>// create a new Target class-object (CreatableEnterpriseManagementObject) and add it to the projection as it is a member of a Membership RelationshipType (as explained above)
                    // notice that we DON'T remove such a Target class-object Relationship because it will also remove the class-object itself (because it is a Membership RelationshipType object and it cannot exist without this Relationship)
                    // we need it to exist because we are copying data from it and it needs to still exist in the db (ex. Attachments - we still need the binary data to exist in the db when we create the new Attachment object)
                    // we could of course delete it after we create the new WorkItem with its Relationships when calling "workItem.Overwrite()", but I chose not to do it</strong></span>

                    if (relationship.IsSubtypeOf(membershipRelationshipClass))
                    {
                        CreatableEnterpriseManagementObject instance = new CreatableEnterpriseManagementObject(emg, itemProjection.Object.GetClasses(BaseClassTraversalDepth.None).FirstOrDefault());
                        foreach (ManagementPackProperty property in itemProjection.Object.GetProperties())
                        {
                            instance[property.Id].Value = itemProjection.Object[property.Id].Value;
                        }

                        instance[null, Constants.entityId].Value = Guid.NewGuid().ToString();

                        workItem.Add(instance, relationship.Target);
                    }

                    <span style="color: #339966"><strong>// just add the existing Target object-class as it is not a member of a Membership RelationshipType (as explained above)</strong></span>

                    else
                    {
                        workItem.Add(itemProjection.Object, relationship.Target);
                        itemProjection.Remove();
                    }
                }
            }

            if(incident[relationship.Source].Any())
            {
                <span style="color: #339966"><strong>// we just create the new Relationship of the Source class-object to the new WorkItem because this is not affected by the Membership RelationshipType</strong></span>

                foreach (IComposableProjection itemProjection in incident[relationship.Source])
                {
                    workItem.Add(itemProjection.Object, relationship.Source);
                    itemProjection.Remove();
                }
            }
        }

        <span style="color: #339966"><strong>// this is where we actually save (write) the new data to the db, when calling "Overwrite()" - here saving the Incident we modified (set Status to Closed &amp; deleted Relationships)
        // before we have just created the new objects and relationships in-memory
        // this is also the point when almost all of the code validation is being done
        // if there are any issues really creating/editing/adding these objects/realtionships, this is where we would get the errors</strong></span>

        incident.Overwrite();

        <span style="color: #339966"><strong>// we are want to handle the error here of saving the new WorkItem and its Relationships because we want to re-open the Incident in case there is an issue when creating the new WorkItem</strong></span>

        try
        {
            <span style="color: #339966"><strong>// this is where we actually save (write) the new data to the db, when calling "Overwrite()" - here saving the new WorkItem we created with its Relationships we added (from the Incident)</strong></span>

            workItem.Overwrite();
        }
        catch (Exception ex)
        {
            <span style="color: #339966"><strong>// if we faild to create the new WorkItem with its Relationships, we want to revert to setting the Incident to an Active Status (we re-open the Incident)</strong></span>

            ManagementPackEnumerationCriteria incidentActiveEnumCriteria = new ManagementPackEnumerationCriteria(string.Format("Name = '{0}'", EnumTypes.incidentStatusActive));
            ManagementPackEnumeration incidentActiveStatus = emg.EntityTypes.GetEnumerations(incidentActiveEnumCriteria).FirstOrDefault();

            incident.Object[incidentClass, IncidentProperties.Status].Value = incidentActiveStatus.Id;
            incident.Object[incidentClass, IncidentProperties.ClosedDate].Value = null;

            <span style="color: #339966"><strong>// again, after applying the new modifications in memory, we need to actually write them to the db using "Overwrite()"</strong></span>

            incident.Overwrite();

            <span style="color: #339966"><strong>// no need to show this because we are just passing it (throwing) to the wrapped try/catch block so it will be displayed and handled there</strong></span>

            throw ex;
        }
    }

    <span style="color: #339966"><strong>// if everything succeeds, we want to refresh the View (in this case, some View that shows Incidents as this is where we are calling our Task from)
    // we want to refresh the view to show the new Status of the Incient (as Closed in this case) - if the View only shows non-Closed Incidents, it will dissapear from the View</strong></span>

    RequestViewRefresh();
}
catch(Exception ex)
{
    <span style="color: #339966"><strong>// we want to handle all Exceptions here so that the Console does not crash
    // we also want to show a MessageBox window with the Exception details for troubleshooting purposes</strong></span>

    MessageBox.Show(string.Format("Error: {0}: {1}\n\n{2}", ex.GetType().ToString(), ex.Message, ex.StackTrace));
}</span></pre>
&nbsp;

Have fun coding! :D]]></content:encoded>
    </item>
    <item>
      <title>Export and Import data of a MP in Service Manager when the MP needs to be removed as it cannot be upgraded (breaking change)</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/export-and-import-data-of-a-mp-in-service-manager-when-the-mp-needs-to-be-removed-as-it-cannot-be-upgraded-breaking-change</link>
      <pubDate>Wed, 19 Oct 2016 19:57:11 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/?p=695</guid>
      <description><![CDATA[Ever authored a Management Pack and after it is in production for quite some time, you figured out...]]></description>
      <content:encoded><![CDATA[Ever authored a Management Pack and after it is in production for quite some time, you figured out that you need to make a breaking change - one that will require you to remove the MP first as it cannot be upgraded? Such a scenario would be needed if for some reason, you want to delete a Property of a Class for some reason.

But wait ... if we remove the MP, doesn't that mean that all the data in the database (instances &amp; relationships) related to this MP, will be deleted? ... Yup, unfortunately it does ...

So, here is a PowerShell script that can be executed on a SM Management Server, which gets the (internal) name of the MP you need to remove and which will export (in memory) all the data (instances &amp; relationships) related to the MP. It will then stop and wait for your key-press to continue.

Once it is waiting, you can delete the MP and re-import the updated version of the MP that has the change you made.

At this point, you can press any key in the PowerShell window where the script is waiting and it will start to create all instances &amp; relationships that existed prior to removing the MP.

&nbsp;

<strong><span style="color: #ff0000">NOTE:</span> Please be aware that I have tested only SOME scenarios. It might be that this will either fail, or not be able to re-create everything properly in who-knows-what-corner-case-scenarios. Please try to use and test this in pre-production if possible, and ALWAYS take a FRESH Full Backup of the ServiceManager database before attempting this in production.</strong>

&nbsp;
<pre class="trace"><span style="font-size: small">$mpName = "<span style="color: #ff6600">MPClassesHostingTest</span>" <span style="color: #008000"># internal MP Name goes here</span>
$message = "Perform the needed actions here (remove MP, re-import, etc.). After finishing the actions, press any key to continue."
$props = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\System Center\2010\Common\Setup"
$instdir = $props.InstallDirectory
Add-Type -Path "$instdir`SDK Binaries\Microsoft.EnterpriseManagement.Core.dll"
$dataMap = @{}
$emg = New-Object Microsoft.EnterpriseManagement.EnterpriseManagementGroup("localhost")
$mp = Get-SCManagementPack -Name $mpName
# sort (descending) by Hosted classes first so that when we re-create the objects, we start re-creating the Hosted objects first
# this is needed because Hosted objects need to be created together with their HostING objects
# this way, when we create non-Hosted objects, we skip creating HostING objects which we already have created when creating their Hosted objects
$classList = Get-SCClass -ManagementPack $mp | ? { $_.Singleton -eq $false -and $_.Abstract -eq $false } | Sort-Object Hosted -Descending
$hostingRel = Get-SCRelationship -Name "System.Hosting"
foreach($class in $classList) {
    $instanceList = Get-SCClassInstance -Class $class
    foreach($instance in $instanceList) {
        $object = @{
            instance = $instance;
            rels = @{
                source = Get-SCRelationshipInstance -SourceInstance $instance | ? { $_.IsDeleted -eq $false -and $_.Name -ne "System.Hosting" };
                target = Get-SCRelationshipInstance -TargetInstance $instance | ? { $_.IsDeleted -eq $false -and $_.Name -ne "System.Hosting" };
            };
        }
        $dataMap.Add($instance.EnterpriseManagementObject.Id, $object)
    }
}
if($psISE) {
    Add-Type -AssemblyName System.Windows.Forms
    [System.Windows.Forms.MessageBox]::Show("$message")
} else {
    Write-Host "$message" -ForegroundColor Yellow
    $x = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
# Create all objects first so that we are sure we can use them for relationships afterwards
# These need to be all there created first in order (non-Hosted first &amp; Hosted after)
foreach($key in $($dataMap.Keys)) {
    $entry = $dataMap.Item($key)
    $class = Get-SCClass -Name $entry.instance.EnterpriseManagementObject.GetClasses().Name
    $props = @{}
    if($class.Hosted -eq $true) {
        # need to handle Hosted classes differently (cannot use New-SCClassInstance cmdlet for various corner-cases)
        # handling with CreatableEnterpriseManagementObject instead (need to also create parent-Hosting class together with it)
        $hostingClass = $class.GetParentClasses([Microsoft.EnterpriseManagement.Configuration.DerivedClassTraversalDepth]::Recursive, $hostingRel, [Microsoft.EnterpriseManagement.Common.TraversalDepth]::OneLevel).Item(0)
        $hostingClassKey = $hostingClass.GetKeyProperties().Item(0)
        $object = New-Object -TypeName Microsoft.EnterpriseManagement.Common.CreatableEnterpriseManagementObject($emg, $hostingClass)
        $object.Item($hostingClass, $hostingClassKey.Name).Value = $entry.instance.$($hostingClassKey.Name)
        $object.Commit()
        $object = New-Object -TypeName Microsoft.EnterpriseManagement.Common.CreatableEnterpriseManagementObject($emg, $class)
        $object.Item($hostingClass, $hostingClassKey.Name).Value = $entry.instance.$($hostingClassKey.Name)
        foreach($property in $class.GetProperties([Microsoft.EnterpriseManagement.Configuration.BaseClassTraversalDepth]::Recursive)) {
            if($entry.instance.$($property.Name) -ne $null) {
                $object.Item($class, $property.Name).Value  = $entry.instance.$($property.Name)
            }
        }
        $object.Commit()
        $entry.instance = $object
    } elseif((Get-SCClassInstance -Id $entry.instance.EnterpriseManagementObject.Id) -eq $null) {
        foreach($property in $class.GetProperties([Microsoft.EnterpriseManagement.Configuration.BaseClassTraversalDepth]::Recursive)) {
            if($entry.instance.$($property.Name) -ne $null) {
                $props.Add($property.Name, $entry.instance.$($property.Name))
            }
        }
        $entry.instance = New-SCClassInstance -Class $class -Property $props -PassThru
    }
    $dataMap.Set_Item($key, $entry)
}
# Now that we know we have all objects created, we can safely create the Relationships
foreach($key in $dataMap.Keys) {
    $entry = $dataMap.Item($key)
    foreach($rel in $entry.rels.Item("source")) {
        $relType = Get-SCRelationship -Id $rel.RelationshipId
        $target = Get-SCClassInstance -Id $rel.TargetObject.Id
        if($target -ne $null) {
            New-SCRelationshipInstance -RelationshipClass $relType -Source $entry.instance -Target $target
        }
    }
    foreach($rel in $entry.rels.Item("target")) {
        $relType = Get-SCRelationship -Id $rel.RelationshipId
        $source = Get-SCClassInstance -Id $rel.SourceObject.Id
        if($source -ne $null) {
            New-SCRelationshipInstance -RelationshipClass $relType -Source $source -Target $entry.instance
        }
    }
}
</span></pre>]]></content:encoded>
    </item>
    <item>
      <title>Troubleshooting LFX Connectors in Service Manager - the SCCM Connector where LastInventoryDate is not getting updated</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/troubleshooting-lfx-connectors-in-service-manager-the-sccm-connector-where-lastinventorydate-is-not-getting-updated</link>
      <pubDate>Wed, 05 Oct 2016 17:58:52 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/?p=685</guid>
      <description><![CDATA[Hi everyone! :D It's been a while since my last post. I've been pretty busy with migrating to the...]]></description>
      <content:encoded><![CDATA[Hi everyone! :D It's been a while since my last post. I've been pretty busy with migrating to the cloud, hehe

I do have some posts however, which I wanted to write and never got the chance to yet. So, let's continue with the articles - this is one of them about troubleshooting LFX Connectors in Service Manager.

Enjoy!

&nbsp;

First, try to concentrate only on specific stuff (if there is more than 1 issue, we need to take them one after the other):
<ul>
 	<li>Choose a single Computer that has the issue for which data should get imported / updated from SCCM through the SCCM Connector</li>
 	<li>Choose a specific type of data (field) – here we may start with <span style="color: #ff6600"><strong>LastInventoryDate</strong> </span>not getting updated (focusing on the Computer we selected)</li>
</ul>
You can also have a look at this article which explains a little bit about how LFX Connectors work and check out if BatchSize(es) for the Data that is missing is high enough in relation to how much data is getting imported:
<ul>
 	<li><a href="https://blogs.technet.microsoft.com/mihai/2013/08/13/tweaking-the-ad-and-cm-connectors-in-service-manager-2012/">https://blogs.technet.microsoft.com/mihai/2013/08/13/tweaking-the-ad-and-cm-connectors-in-service-manager-2012/</a></li>
</ul>
he different types of data import template definitions for the SCCM 2012+ Connector are defined in the <span style="color: #ff6600"><strong>Microsoft.EnterpriseManagement.ServiceManager.Connector.Sms2011</strong></span> MP and you can export this MP using this query to understand the definitions:
<pre class="trace"><span style="font-size: small"><strong>select MPName, convert(xml, MPXML)
from ManagementPack
where MPName = '<span style="color: #ff6600">Microsoft.EnterpriseManagement.ServiceManager.Connector.Sms2011</span>'
</strong></span></pre>
All this, is stored in the <strong>LFX.DataTable</strong> with specific <strong>DataName</strong> – here, we will have LFX Staging Table and View information together with the Queries used to get the data from the direct source (here SCCM site database) and afterwards from the LFX Staging Tabled, import it into the SM (CMDB) Instance Space (tables) =&gt; <strong><em>BME</em></strong>/<strong><em>TME</em></strong>, <strong>MT_<em>ClassName</em></strong> and <strong><em>Relationship</em></strong> tables.

Here is a Query to have a general overview of the information needed (for now, for all the DataTables of the SCCM 2012+ Connector):
<pre class="trace"><span style="font-size: small"><strong>select *
from LFX.DataTable
where DataName like '%<span style="color: #3366ff">CMv5_</span>%'
</strong></span></pre>
Notice how some <strong>DataName</strong>s have a “<strong><em>Cached_</em></strong>” prefix in their name. This is because:
<ul>
 	<li>The ones without the “<strong><em>Cached_</em></strong>” prefix are the ones which are being used by the <strong><em>Data Provider</em></strong> (gets the data directly from the custom source – in this case, the SCCM site database)</li>
 	<li>The ones that have “<strong><em>Cached_</em></strong>” prefix are the ones used by the <strong><em>Data Consumer</em></strong> that will get the already imported data (from the LFX Staging Tables) and import it into the instance space (only then will it be visible in the Console)</li>
</ul>
&nbsp;

This is important because if you look at the <span style="color: #3366ff"><strong>QueryString</strong></span> field, you can see the SQL Query that will be executed to get that data.

&nbsp;

Let’s search for the type of data we are interested in (<span style="color: #ff6600"><strong>LastInventoryDate</strong></span>) directly in the XML definition of the MP and we find it here:
<pre class="trace"><span style="font-size: small"><strong><span style="color: #ff6600">&lt;Object Path</span>="$Context/Path[Relationship='LFX!System.LinkingFramework.ConnectorEmbedsTables' SeedRole='Source' TypeConstraint='LFX!System.LinkingFramework.DataTable']$"&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/<span style="color: #ff6600">DataName</span>$"&gt;<span style="color: #3366ff">Cached_CMv5_LogicalComputers</span>&lt;/Property&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/WatermarkField$"&gt;E.Lfx_Timestamp&lt;/Property&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/WatermarkType$"&gt;0&lt;/Property&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/BatchIdField$"&gt;E.Lfx_RowId&lt;/Property&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/BatchIdType$"&gt;0&lt;/Property&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/BatchIdSize$"&gt;500&lt;/Property&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/UseCache$"&gt;false&lt;/Property&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/QueryString$"&gt;
                                         SELECT E.Lfx_RowId,
                                                       E.Lfx_SourceID,
                                                       E.Lfx_Status,
                                                       E.DisplayName, 
                                                       E.PrincipalName, 
                                                       E.NetbiosComputerName, 
                                                       E.NetbiosDomainName,
                                                       E.OffsetInMinuteFromGreenwichTime,
                                                       E.IsVirtualMachine,
                                                       E.<span style="color: #ff6600">LastInventoryDate</span>,
                                                       E.ActiveDirectorySite
                                         from [LFXSTG].<span style="color: #993366">v_Cached_CMv5_LogicalComputers</span> E 
                                  &lt;/Property&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/CollectionName$"&gt;Cached_CMv5_LogicalComputers&lt;/Property&gt;
       &lt;Property Path="$Context/Property[Type='LFX!System.LinkingFramework.DataTable']/DependOnDataTable$"&gt;Cached_CMv5_PhysicalComputers&lt;/Property&gt;
<span style="color: #ff6600">&lt;/Object&gt;
</span></strong></span></pre>
We can figure out from here, that the <span style="color: #ff6600"><strong>LastInventoryDate</strong> </span>value is coming from the <span style="color: #3366ff"><strong>v_Cached_CMv5_LogicalComputers</strong></span> View (notice the <strong><em>v_</em></strong> at the beginning of the name).

What we can also figure out already from the definition above, is that this depends on another view called <span style="color: #3366ff"><strong>Cached_CMv5_PhysicalComputers</strong></span> (just add a “<strong><em>v_</em></strong>” as prefix if you want to query it – and don’t forget that it belongs to the <strong><em>LFXSTG</em></strong> schema).

&nbsp;

So, let’s have a look from SQL Management Studio at the definition of this view <span style="color: #3366ff"><strong>v_Cached_CMv5_LogicalComputers</strong></span>:
<pre class="trace"><span style="font-size: small"><strong>CREATE VIEW [LFXSTG].[v_Cached_CMv5_LogicalComputers] AS
SELECT S.Lfx_RowId,
        S.Lfx_SourceID,
        S.Lfx_Timestamp,
        CCX.Lfx_Status,
        CCX.Name0 AS 'DisplayName', 
        COALESCE(CCX.Name0, S.Netbios_Name0) 
              + '.' + COALESCE(CCX.Domain0, S.Resource_Domain_OR_Workgr0) AS 'PrincipalName', 
        S.Netbios_Name0 AS 'NetbiosComputerName', 
        S.Resource_Domain_OR_Workgr0 AS 'NetbiosDomainName',
        CCX.CurrentTimeZone0 AS 'OffsetInMinuteFromGreenwichTime',
        CCX.IsVirtualMachine,
        <span style="color: #ff00ff">W</span>.<span style="color: #339966">LastHWScan </span>AS '<span style="color: #ff6600">LastInventoryDate</span>',
        S.AD_Site_Name0 AS 'ActiveDirectorySite'
FROM LFXSTG.CMv5_SYSTEM S
CROSS APPLY 
LFXSTG.fn_CheckCMv5CachedComputers(S.Lfx_SourceID, S.ResourceID, S.SMS_Unique_Identifier0, S.Lfx_Status) AS CCX
    LEFT JOIN <span style="color: #ff6600">LFXSTG</span>.<span style="color: #993366">CMv5_WORKSTATION_STATUS</span> <span style="color: #ff00ff">W</span>
        ON S.ResourceID = W.ResourceID AND S.Lfx_SourceId = W.Lfx_SourceId
WHERE S.Netbios_Name0 IS NOT NULL 
    AND S.Resource_Domain_OR_Workgr0 IS NOT NULL
    AND CCX.Lfx_Status != 'I'
</strong></span></pre>
So now we figure out that we get the <span style="color: #ff6600"><strong>LastInventoryDate</strong> </span>value from <span style="color: #339966"><strong>LastHWScan</strong> </span>field of the <span style="color: #ff6600"><strong>LFXSTG</strong></span><strong>.</strong><span style="color: #993366"><strong>CMv5_WORKSTATION_STATUS</strong></span> table.

&nbsp;

This also tells us, that this is the <strong>Data Consumer</strong> part (notice the “<strong><em>Cached_</em></strong>” prefix in the <strong>DataName</strong>). So how are we getting this data in the table?

The table name is <span style="color: #ff6600"><strong>CMv5_WORKSTATION_STATUS</strong></span> and so we can look for the <span style="color: #3366ff"><strong>QueryString</strong> </span>in the <strong>LFX.<span style="color: #339966">DataTable</span></strong> by its name:
<pre class="trace"><span style="font-size: small"><strong>select *
from LFX.DataTable
where DataTableName = '<span style="color: #ff6600">CMv5_WORKSTATION_STATUS</span>'
</strong></span></pre>
So here we are, this is the Query we are executing directly on the SCCM site database to get the data from:
<pre class="trace"><span style="font-size: small"><strong>
SELECT
       S.ChangeAction as Lfx_Status,
       S.ResourceID,
       S.BatchingKey,
       S.GroupKey,
       S.TimeStamp,
       <span style="color: #ff00ff">S</span>.<span style="color: #ff6600">LastHWScan</span>,
       S.SystemDefaultLCID,
       S.TimezoneOffset,
       S.LastReportVersion
FROM <span style="color: #3366ff">SCCM_Ext.vex_GS_WORKSTATION_STATUS</span> <span style="color: #ff00ff">S</span>
INNER JOIN SCCM_Ext.vex_FullCollectionMembership CM
ON S.ResourceID = CM.ResourceID
INNER JOIN SCCM_Ext.vex_Collection C
ON C.CollectionID = CM.CollectionID
WHERE S.LastHWScan IS NOT NULL 
AND C.ChangeAction = 'U' and CM.ChangeAction = 'U'
AND $COLLECTIONLIST
ORDER BY S.rowversion
</strong></span></pre>
We can see that we get the <span style="color: #339966"><strong>LastHWScan</strong></span> value from the <span style="color: #ff6600"><strong>SCCM_Ext.vex_GS_WORKSTATION_STATUS</strong></span> table/view from the SCCM site database.
<ul>
 	<li>Notice <span style="color: #993366"><strong><em>$COLLECTIONLIST</em></strong></span> here – this is replaced with the SCCM Site Collection filters that you have configured in your SCCM Connector.</li>
</ul>
&nbsp;

Data to collect while we let the affected SCCM Connector (responsible for the chosen Computer) run until it finishes, would be:
<ul>
 	<li>SQL Profiler trace on the SCCM Site database</li>
 	<li>SQL Profiler trace on the ServiceManager database</li>
 	<li>SM ETW Trace on LFX Connectors: <strong>cmd -l VER -a <span style="color: #808000">CON</span></strong></li>
</ul>
&nbsp;

In the SQL Profiler Trace of the SCCM Site database, look for the query that we have identified that gets the data – and ideally, run it manually to see what data you get as result from the SCCM Site database.

After this, look in the SQL Profiler Trace of the ServiceManager database and look at the other query that we identified that gets the data from the LFXSTG tables/views (as explained/identified above).

&nbsp;

Identify the <span style="color: #ff6600"><strong>ResourceId</strong> </span>of the Computer you are looking for and you can check if it is being synchronized by which and what Connectors using this query (on the ServiceManager database):
<pre class="trace"><span style="font-size: small"><strong>select
       wss.Lfx_RowId,
       wss.Lfx_Timestamp,
       ds.DisplayName,
       wss.Lfx_Status,
       wss.ResourceID,
       wss.BatchingKey,
       wss.GroupKey,
       wss.TimeStamp,
       wss.LastHWScan,
       wss.SystemDefaultLCID,
       wss.LastReportVersion
from LFXSTG.CMv5_WORKSTATION_STATUS wss
join LFX.DataSource ds
       on wss.Lfx_SourceId = ds.DataSourceId
where wss.ResourceId in (<span style="color: #ff0000"><em>RES_ID_1</em></span>, <span style="color: #ff0000"><em>RES_ID_2</em></span>, <span style="color: #ff0000"><em>RES_ID_3</em></span>, <span style="color: #ff0000"><em>RES_ID_ETC</em></span>)
</strong></span></pre>
Now another thing we may want to know about (as you might have noticed from the SQL Profiler queries and <strong>Batch</strong>/<strong>WaterMark</strong> fields in the <strong><em>LFX.DataTable</em></strong>), is that we import data in batches and that we also use a WaterMark field (defined in the <strong><em>LFX.DataTable</em></strong>) to keep track of where we left of the on the previous time to only get new data on next runs.

&nbsp;

We are keeping track of the <strong>WaterMark</strong> for each <strong>DataName</strong> in the <strong>LFX.<span style="color: #0000ff">ClientWorkTable</span></strong> table:
<pre class="trace"><span style="font-size: small"><strong>select
       cwt.ClientWorkTableId as [WorkTableId],
       cwt.Watermark as [WaterMark],
       cwt.LastSyncTime as [LastSyncTime],
       ds.DataSourceName as [ConnectorName],
       ds.DisplayName as [ConnectorDisplayName],
       dt.DataName as [DataName],
       dt.DataTableName as [DataTableName],
       (
              case
                     when dt.WatermarkType = -1 then 'None'
                     when dt.WatermarkType = 0 then 'DateTime'
                     when dt.WatermarkType = 1 then 'Timestamp'
                     when dt.WatermarkType = 2 then 'Number'
                     when dt.WatermarkType = 3 then 'Number'
              end 
       ) as [WaterMarkType]
from LFX.<span style="color: #3366ff">ClientWorkTable</span> as cwt
inner join LFX.DataSource as ds
       on ds.DataSourceId = cwt.DataSourceId
inner join LFX.DataTable as dt
       on dt.DataTableId = cwt.DataTableId
</strong></span></pre>
To reset the <strong>WaterMark</strong> for the <span style="color: #ff6600"><strong>CMv5_WORKSTATION_STATUS</strong></span> <strong>DataName</strong> for example, so that the SCCM Connector will try to resynchronize all the data type available in SCCM again, we can run this query:
<ul>
 	<li>Repace “<span style="color: #ff0000"><strong><em>AD_CONNECTOR_DSIPLAYNAME</em></strong></span>” with the DisplayName of the (SCCM) Connector which you are interested in (as seen from the results of the previous query).</li>
 	<li>Pay attention to the <span style="color: #3366ff"><strong>WaterMarkType</strong> </span>and based on that, understand what type of value we need to set in order for the WaterMark to be set to “0” and try to re-sync everything related to this type of data (in this example <span style="color: #ff6600"><strong>CMv5_WORKSTATION_STATUS</strong></span>)</li>
</ul>
<pre class="trace"><span style="font-size: small"><strong>update cwt
set cwt.Watermark = 0x00000000
from LFX.ClientWorkTable as cwt
inner join LFX.DataSource as ds
       on ds.DataSourceId = cwt.DataSourceId
inner join LFX.DataTable as dt
       on dt.DataTableId = cwt.DataTableId
where
       ds.DisplayName = '<span style="color: #ff0000"><em>REPLACE_WITH_</em><em>CONNECTOR_DSIPLAYNAME_STRING_HERE</em></span>' and
       dt.DataName = '<span style="color: #ff6600">CMv5_WORKSTATION_STATUS</span>'
</strong></span></pre>]]></content:encoded>
    </item>
    <item>
      <title>Improving Service Manager - we're not kidding!</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/improving-service-manager-were-not-kidding</link>
      <pubDate>Tue, 28 Apr 2015 14:15:05 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/2015/04/28/improving-service-manager-were-not-kidding/</guid>
      <description><![CDATA[Update Rollup 6 is out! :)
http://support.microsoft.com/kb/3039363

We are constantly improving...]]></description>
      <content:encoded><![CDATA[<p>Update Rollup 6 is out! :)</p>
<p><a href="http://support.microsoft.com/kb/3039363" title="Update Rollup 6 for System Center 2012 R2 Service Manager">http://support.microsoft.com/kb/3039363</a></p>
<p></p>
<p>We are constantly improving SC Service Manager and we&#39;re not kidding about it ;)</p>
<p>The fixes and performance improvement in Update Rollup 6 are a proof of this!</p>
<p></p>
<p>Great job guys!</p>
<p></p>
<p>Enjoy!</p>
<p></p>
<p></p>
<p></p>
<p></p>]]></content:encoded>
    </item>
    <item>
      <title>Free ebook: Microsoft System Center Operations Manager Field Experience</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/free-ebook-microsoft-system-center-operations-manager-field-experience</link>
      <pubDate>Wed, 22 Apr 2015 02:24:37 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/2015/04/22/free-ebook-microsoft-system-center-operations-manager-field-experience/</guid>
      <description><![CDATA[So, here&#39;s a cool ebook on OpsMgr for you!...]]></description>
      <content:encoded><![CDATA[<p>So, here&#39;s a cool ebook on OpsMgr for you! :)</p>
<p><a href="http://blogs.msdn.com/b/microsoft_press/archive/2015/04/21/free-ebook-microsoft-system-center-operations-manager-field-experience.aspx">http://blogs.msdn.com/b/microsoft_press/archive/2015/04/21/free-ebook-microsoft-system-center-operations-manager-field-experience.aspx</a></p>
<p>Check out the description - the contents are pretty interesting as we are explaining a lot of inside knowledge about deployment, optimizations, troubleshooting and internals of the product :D</p>
<p></p>
<p>Enjoy!</p>
<p></p>
<p></p>
<p></p>]]></content:encoded>
    </item>
    <item>
      <title>Improvements are here for the Data Warehouse and others in Update Rollup 5</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/improvements-are-here-for-the-data-warehouse-and-others-in-update-rollup-5</link>
      <pubDate>Thu, 12 Feb 2015 08:20:00 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/2015/02/12/improvements-are-here-for-the-data-warehouse-and-others-in-update-rollup-5/</guid>
      <description><![CDATA[Update Rollup 5 is here: http://support.microsoft.com/kb/3009517
Beside other cool fixes, this UR...]]></description>
      <content:encoded><![CDATA[<p><strong>Update Rollup 5</strong> is here: <a title="Update Rollup 5" href="http://support.microsoft.com/kb/3009517" target="_blank">http://support.microsoft.com/kb/3009517</a></p>
<p>Beside other cool fixes, this UR includes also some cool changes for the Data Warehouse component. These will make it much easier to troubleshoot possible issues that may appear.</p>
<p>This is part of our effort to improve the Data Warehouse and the Service Manager product in general. I hope you will like it and await more good news in the future :D</p>
<p></p>
<p><strong>INFOS:</strong></p>
<p><strong>&nbsp;</strong></p>
<p><strong>Note</strong>&nbsp;The System Center 2012 R2 Service Manager Update Rollups are cumulative. Therefore, this update rollup contains new fixes for the following issues along with fixes that were included in System Center 2012 R2 Service Manager&nbsp;<a title="/kb/2989601" class="KBlink" href="http://support.microsoft.com/kb/2989601" target="self">Update Rollup 4</a>, <a title="/kb/2962041" class="KBlink" href="http://support.microsoft.com/kb/2962041" target="self">Update Rollup 3</a>, and <a title="/kb/2904710" class="KBlink" href="http://support.microsoft.com/kb/2904710" target="self">Update Rollup 2</a>.</p>
<ul>
<li>Change request still stays &quot;in progress&quot; when last activity is skipped and all previous activities are completed.<br /><br /></li>
<li><b>ActualStartDate</b> and <b>ActualEndDate</b> field values for Change Request and Release Request do not set.<br /><br /></li>
<li>Multiple System Center Service Manager Connectors to System Center Configuration Manager execute and complete successfully. However, the start, finish, and status property values are not updated in the Service Manager Console under the Connectors view, and event 3334 is logged.<br /><br /></li>
<li>Trying to delete a Service Request template that is being used by a Request Offering causes a cryptic and non-user-friendly error message.<br /><br /></li>
<li>The &quot;Group By&quot; functionality in a view does not work correctly when the <strong class="uiterm">Group By</strong> column has empty fields.<br /><br /></li>
<li>The console crashes when the user tries to open an already opened attachment from a Work Item form.<br /><br /></li>
<li>Opening the Views for Groups takes a long if there are a large number of explicit members in the groups.<br /><br /></li>
<li>The OM CI connector fails if you try to import a distributed application that contains an instance of the <b>Hyper-V Virtual Network Adapter</b> class.<br /><br /></li>
<li>Monitoring Host process crashes if there exists a notification after the user who created it was deleted or moved to a hidden organizational unit (OU) in Active Directory.<br /><br /></li>
<li>An exception is raised if a user tries to open a sorted view that is created by using TypeProjection on a custom class that is neither Abstract and nor a first Concrete class.<br /><br /></li>
<li>An exception is thrown when a user tries to open the <strong class="uiterm">Service Components</strong>&nbsp;tab on the Service Maps form when there are large number of services in CMDB.<br /><br /></li>
<li>Enhanced in-event logging for&nbsp;<b>DW jobs</b>.<br /><br />Logging the batch start and completion events for all DW job categories in event log. The start and completion event will include the following:
<ul>
<li>Process category</li>
<li>Process name</li>
<li>Batch ID</li>
<li>Batch start or completion time</li>
</ul>
<br /><br /></li>
<li>Enhanced in event logging for <b>DW cube processing</b>.
<ul>
<li>Time taken by Cube&rsquo;s batch ID to complete will be logged in seconds.</li>
<li>Information about whether the cube is processed under Analysis Services that are running in Microsoft SQL Server Standard Edition or in SQL Server Enterprise Edition.</li>
<li>Event logs will be added during processing of each Dimension and Measure Group for each partition (if applicable) for both enterprise and standard editions of SQL Server.&nbsp;</li>
</ul>
<br /><br /></li>
<li>Added the new Windows PowerShell cmdlet&nbsp;<b>Get-SCDWInfraLocations </b>on the Service Manager management server to retrieve the following location information about its data warehouse infrastructure:
<ul>
<li>Service Manager database</li>
<li>Service Manager data warehouse database</li>
<li>Service Manager Analysis server database</li>
<li>Data Warehouse Reporting Server database and Report Server URL</li>
</ul>
<p style="padding:0;margin:0;"></p>
</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Service Manager Data Warehouse Troubleshooting</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/service-manager-data-warehouse-troubleshooting</link>
      <pubDate>Mon, 24 Nov 2014 18:37:00 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/2014/11/24/service-manager-data-warehouse-troubleshooting/</guid>
      <description><![CDATA[There are some great articles out there which talk about troubleshooting the Data Warehouse. In this...]]></description>
      <content:encoded><![CDATA[<p>There are some great articles out there which talk about troubleshooting the Data Warehouse. In this article I will be going into explaining the internals of the Data Warehouse along with troubleshooting information.</p>
<p>It is important to first of all understand how the DW Jobs work. There are some Jobs that are only visible by looking into the database, others may be seen in PowerShell only and the most basic ones can be seen in the Console. From the perspective of the databases, the <strong>DW Jobs are actually called <span style="color:#ff6600;background-color:#ffffff;">Processes</span></strong>. <em>From now on, I will refer to the DW Jobs as <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span> in this article</em>.</p>
<p>The DW Processes are actually categorized like this:</p>
<ul>
<li><span style="color:#000080;"><strong>Process&nbsp;Categories</strong></span> - this is&nbsp;top level way of categorizing <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span> <em>(Jobs)</em></li>
<li><span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span>&nbsp;- these are the actual&nbsp;<span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span> that exist (ex. <strong>DWMaintenance, MPSyncJob, Extract, Transform, Load,</strong> etc.)</li>
<li><span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModules</strong></span>&nbsp;- each <span style="color:#ff6600;background-color:#ffffff;"><strong>Process </strong></span>has several&nbsp;<span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModules</strong></span> which it will actually execute in order to &quot;finish&quot; - there is also a certain order in which these will run depending on dependencies on one another and the level of the modules</li>
</ul>
<p>Now what you need to know is that each <strong>Process</strong> will be executed via a <em>Schedule</em> which is actually a Rule (Workflow that runs on a schedule and starts its owning <strong>Process</strong>). When a <strong>Process</strong> is scheduled (for execution) it will actually get a new <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong> </span>created. Think of a <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span> as a class and of a <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong> </span>as an instance of that class that is actually doing something. It is the same for a <span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModule</strong></span>, each will get a <span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong> </span>when it is scheduled for execution. Because a <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span> can have from one to many <span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModules</strong></span>, when a <span style="color:#339966;background-color:#ffffff;"><strong>Batch </strong></span>is created, it also gets all the <span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong> </span>associated with it (<span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModules </strong></span>of the <strong><span style="color:#ff6600;background-color:#ffffff;">Process</span></strong>).</p>
<p>So, to recap, because we will be using these a lot in this article:</p>
<ul>
<li><span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong> </span>= an instance of a <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span> (which in the Console or PowerShell&nbsp;is a Job)</li>
<li><span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong> </span>= an instance of a <span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModule</strong> </span>of a <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span></li>
</ul>
<p>Important to know and also the way the processing/execution will depend on and work, is that each <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span>, as well as each <span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong> </span>(of a <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span>) will have a certain <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>:</p>
<ul>
<li><strong>Success (1)</strong> - the&nbsp;Batch/WorkItem was successful and at that point the actual Status gets changed to Complete</li>
<li><strong>Failed (2)</strong> - there was an error in the Batch/WorkItem and it will be retried on the next execution</li>
<li><strong>Not Started (3)</strong> - the Batch/WorkItem was scheduled for execution and it will be executed on the next interval (schedule) - this is a good Status, it means there was no error and it will run the next time it needs to</li>
<li><strong>Running (4)</strong> - the Batch/WorkItem is currently running</li>
<li><strong>Stopped (5)</strong> - the Batch/WorkItem was stopped (by the user from the Console - <em>Suspend</em> or PowerShell <em><a title="Stop-SCDWJob" href="http://technet.microsoft.com/en-us/library/hh541729(v=sc.20).aspx" target="_blank">Stop-SCDWJob</a></em>)</li>
<li><strong>Completed (6)</strong> - the Batch/WorkItem has successfully completed without any errors</li>
<li><strong>Waiting (7)</strong> - the Batch/WorkItem is waiting for other Batches/WorkItems to finish first on which they are dependent</li>
</ul>
<p>It is important to know that the actual <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>is important for the <span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong></span>, because the <strong><span style="color:#339966;background-color:#ffffff;">Batch</span> <span style="color:#ff00ff;background-color:#ffffff;">Status</span></strong> depends directly on the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Statuses</strong> </span>of its <span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong> </span>- here are some examples:</p>
<ul>
<li>A <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong> </span>can have the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>set to <strong>Running</strong> while all its <span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong> </span>still have the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>of <strong>Not Started <span style="background-color:#00ff00;">=&gt;</span></strong> this is not a bad thing, it just means that the certain <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong> </span>has received a <em>&quot;start request</em>&quot; from the schedule, but the (first) <span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong></span>(s) cannot run yet because they are waiting on another <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span>/<span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong> </span>(of a different <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>)&nbsp;to finish first</li>
<li>If one of the <span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong> </span>of a <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong> </span>will fail and have a <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>of <strong>Failed</strong>, then the <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong> </span>itself will get the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>of <strong>Failed</strong> <span style="background-color:#00ff00;"><strong>=&gt;</strong></span> all <span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong> </span>need to complete successfully and thus have a <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>of <strong>Completed</strong> for the <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong> </span>to also get the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>of <strong>Completed</strong></li>
</ul>
<p></p>
<p>When a <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong> </span>gets created the first time (on installation or DW registration), a new <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span> will be created with some <strong>BatchId</strong> (the newest one possible - starting from 1 - for the first <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>). Then for each&nbsp;<span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModule</strong></span> of this <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>, a new&nbsp;<span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong></span> with a certain <strong>WorkItemId</strong> will get created for this corresponding <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span>. This will all initially have the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong></span>&nbsp;of <strong>Not Started</strong> and when the corresponding <em>Schedule Rule</em> will reach it schedule it will send a &quot;<em>start request</em>&quot; for it&#39;s <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span>. This will set the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong></span>&nbsp;of that <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span>&nbsp;to <strong>Running</strong>. The actual way how these run is that there is a <em>Rule</em> associated with each&nbsp;<span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span> and these Rules run <em>every <strong>30</strong> seconds</em>. As soon as such a <em>Rule</em> runs, if it sees that its corresponding <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span> has the (latest)&nbsp;<span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span> with a <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong></span>&nbsp;of <strong>Running</strong>, will take the first/next&nbsp;<span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong></span> that has a <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong></span>&nbsp;of <strong>Not Started</strong> (depending on dependencies and level) and will try to execute that <span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong></span>. If it can execute and it is successful, it will get the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>of <strong>Completed</strong> once it finishes. If it fails, then it will get the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>of <strong>Failed</strong>. It is important to know here, that it can and will get a <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong> </span>of <strong>Failed</strong> also without there being an actual error - but rather it cannot start/run right now because a dependent&nbsp;<span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong></span> is not finished yet and thus the <em>&quot;error&quot;</em> is actually &quot;<em>waiting on workitems to finish</em>&quot;.</p>
<p>Another very important thing to know is that there is also a certain synchronization method between the different <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span>, so that they don&#39;t interfere with each others work. This is needed because there are some actions which change the database(s) schema, add/remove columns from tables, indexes, primary/foreign keys, etc. We would not want the ETL (Extract, Transform, Load) <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes </strong></span>to run and copy/transform data&nbsp;while we are doing such changes. Because of this, we have these implementations:</p>
<ul>
<li>When the <strong>DWMaintenance</strong> and/or <strong>MPSyncJob</strong> <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span> start running, the first thing they will do, is disable the ETL <strong>(Extract, Transform, Load)</strong> <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span>&nbsp;<span style="background-color:#00ff00;"><strong>=&gt;</strong></span> it is very important to note here that if either of the ETL <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span>&nbsp;<span style="background-color:#00ff00;"><strong></strong></span>will be running when they will get disabled, these will *<strong>still</strong>* show the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong></span> of <strong>Running</strong>, but in reality they will not run because they get disabled.</li>
<li>Because <strong>DWMaintenance</strong> and <strong>MPSyncJob</strong> <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span> should also not be running at the same time, these use a <em><strong>locking</strong></em> mechanism - whichever of them gets this <strong>lock</strong> first will be allowed to run until it finishes (<span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong></span> of <strong>Completed</strong>) while the other one will remain waiting for it to finish, even if the <span style="color:#ff00ff;background-color:#ffffff;"><strong>Status</strong></span>&nbsp;will still show as&nbsp;<strong>Running </strong>and even if it will <strong>*not*</strong> be directly disabled <span style="background-color:#00ff00;"><strong>=&gt;</strong></span>&nbsp;there is a table in the <strong>DWStagingAndConfig</strong> database used for holding the <strong>lock</strong> which you can look at - it is called <span style="font-size:small;background-color:#ffff00;"><strong>LockDetails</strong></span>.</li>
</ul>
<p></p>
<p>I have talked about some &quot;<em>invisible</em>&quot; Jobs which can only be seen by querying the database. There are actually a lot of those, but the &quot;real&quot; way to talk about them, is to go back to the <span style="color:#000080;"><strong>Process Categories</strong></span>. There is a very important <span style="color:#000080;"><strong>Process Category </strong></span>here which needs to be mentioned, which is the <strong>Deployment</strong> category. This is invisible because the <strong>MPSyncJob</strong> actually takes care handing work over this this category. <strong>MPSyncJob</strong> will associate Management Packs from one data source to another (ex.&nbsp;from CMDB to the DW). Each Management Pack that got associated will get a new Job (<span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>) created for it which falls under the <strong>Deployment</strong> <span style="color:#000080;"><strong>Process Category</strong></span>. We can also refer to this as the &quot;<em><strong>Deployment Job</strong></em>&quot; if you will - and if fact, this is how you would usually hear about this. These are responsible for *<strong>actually</strong>* deploying (or installing if you will) the Management Packs which were synchronized over - without this, nothing would work because we would have no extended information in the Data Warehouse about what <em>Classes, Relationships,</em> etc. we have in the CMDB (and other managed data sources which we can register to the Data Warehouse).</p>
<p>If either of the deployment &quot;jobs&quot; fail or are not yet finished, then you can be more or less sure that nothing will work properly and you will 99% get errors related to either of the ETL <strong>(Extract, Transform, Load)</strong> <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span> and maybe not only those - depending on where deployment is at that point.</p>
<p>While any of the <strong>Deployment</strong> <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span>&nbsp;<span style="background-color:#00ff00;"><strong></strong></span>will follow the same rules as the others, that is get a&nbsp;<span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span> and one to many <span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong></span>, it also has another way of actually making the deployment. Each such <strong>Deployment</strong> <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>&nbsp;(for each Management Pack) will have a new <span style="color:#99cc00;"><strong>DeploySequence</strong></span> created (with a <strong>DeploySequenceId). </strong>Because each Management Pack has one to many &quot;items&quot; <em>(Classes, Relationships,</em> etc.) which need to be deployed, for each <span style="color:#99cc00;"><strong>DeploySequence</strong></span>&nbsp;we will have one to many <span style="color:#808000;"><strong>DeployItems</strong></span> created. This is important information for when you get into the actual troubleshooting part in the database.</p>
<p></p>
<p>In case you are not familiar with the basics of troubleshooting the DW Jobs from PowerShell, I suggest first starting with this article: <a title="http://technet.microsoft.com/en-us/library/hh542403.aspx" href="http://technet.microsoft.com/en-us/library/hh542403.aspx" target="_blank">http://technet.microsoft.com/en-us/library/hh542403.aspx</a></p>
<p>Also, if you are not familiar with what the ETL (<strong>Extract, Transform, Load</strong>) Jobs are and how these work, I suggest reading this article as well: <a title="Analtomy of ETL" href="/b/servicemanager/archive/2009/06/04/data-warehouse-anatomy-of-extract-transform-load-etl.aspx" target="_blank">http://blogs.technet.com/b/servicemanager/archive/2009/06/04/data-warehouse-anatomy-of-extract-transform-load-etl.aspx</a></p>
<p>Remember to always start by checking if there are any Management Packs where they <strong><em>Deployment Status</em></strong> shows as <strong>Failed</strong> in the SvcMgr Console in the <em>Date Warehouse</em> tab under the <em>Management Packs</em> view. For any such Management Pack which is <strong>Failed,</strong> you should run the &quot;<em>Restart Deployment</em>&quot; task from the Console in the tasks pane. If you are lucky, it was just some timeout or deadlock and it will succeed this time. If not, then you can always see errors about this failure as well as any other failures in the DW Jobs by looking into the <span style="background-color:#ff6600;"><strong><em>Operations Manager</em> event log</strong> </span>directly on the SvcMgr Data Warehouse Management Server (filter by sources: <em><strong>Data Warehouse</strong></em> and <em><strong>Deployment</strong></em>).</p>
<p>Additionally, you can try to force reset the DW Jobs and run them in a certain order by using the script from this article: <a title="Resetting and rerunning the DW Jobs" href="/b/mihai/archive/2013/07/03/resetting-and-running-the-service-manager-data-warehouse-jobs-separately.aspx" target="_blank">http://blogs.technet.com/b/mihai/archive/2013/07/03/resetting-and-running-the-service-manager-data-warehouse-jobs-separately.aspx</a></p>
<p></p>
<p>The Data Warehouse database which we are interested in when troubleshooting the DW Jobs is the <strong>DWStagingAndConfig</strong> database. Here is a list of tables&nbsp;of interest when&nbsp;troubleshoot the DW Jobs and at the end, also a file attached with useful sql queries:</p>
<p></p>
<p><span style="font-size:medium;"><strong>1.</strong></span> The <span style="font-size:small;"><strong>Infra.<span style="color:#333399;">ProcessCategory</span></strong></span> table is where all the existing <span style="color:#000080;"><strong>Process&nbsp;Categories</strong></span>&nbsp;are stored. It has a column called <strong>IsEnabled</strong> which needs to be&nbsp;<strong>1</strong> in order for any&nbsp;<span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span> under this&nbsp;<span style="color:#000080;"><strong>Process&nbsp;Category</strong></span>&nbsp;to be able to run - this is only modified (<strong>0</strong> and <strong>1</strong>) by the <strong>DWMaintenance</strong> and/or <strong>MPSyncJobs</strong> when they run - this is how they disable the other <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span>.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/tbl_Infra.ProcessCategory.jpg" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/tbl_5F00_Infra.ProcessCategory.jpg"><img width="943" height="202" style="border-color:currentColor;" alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/tbl_Infra.ProcessCategory.jpg" original-url="http://blogs.technet.com/resized-image.ashx/__size/943x202/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/tbl_5F00_Infra.ProcessCategory.jpg" /></a></p>
<p></p>
<p><span style="font-size:medium;"><strong>2.</strong></span> The <span style="font-size:small;"><strong>Infra.<span style="color:#ff6600;background-color:#ffffff;">Process</span></strong></span> table is where all existing <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes </strong></span>are available and classified&nbsp;on <span style="color:#000080;"><strong>Process&nbsp;Categories</strong></span>&nbsp;via the <strong>ProcessCategoryId</strong> column. These also have a <strong>IsEnabled</strong> column which should always be <strong>1 </strong>in order for them to be able to execute. The only reason why either of these would have <strong>IsEnabled</strong> set to <strong>0</strong> is if anyone explicitly disabled these by using the <em><a title="Disable-SCDWJob" href="http://technet.microsoft.com/en-us/library/hh541735%28v=sc.20%29.aspx" target="_blank">Disable-SCDWJob</a></em> CMDLet, which should never be done. To disable a&nbsp;<span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span> (Job) always disable only its Schedule by using <em><a title="Disable-SCDWJobSchedule" href="http://technet.microsoft.com/en-us/library/hh541731%28v=sc.20%29.aspx" target="_blank">Disable-SCDWJobSchedule</a></em>. In the screenshot below, I have explicitly filtered for only the <em>&quot;common&quot;</em> <span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span>, but if you will query the entire table, you will see all of them.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/Infra.Process.jpg" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/Infra.Process.jpg"><img width="807" height="309" style="border-color:currentColor;" alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/Infra.Process.jpg" original-url="http://blogs.technet.com/resized-image.ashx/__size/807x309/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/Infra.Process.jpg" /></a></p>
<p></p>
<p><span style="font-size:medium;"><strong>3.</strong></span> The <span style="font-size:small;"><strong>Infra.</strong><span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModule</strong></span></span> table is where all existing <span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModules</strong></span> are located and are classified on each <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span> via the <strong>ProcessId</strong> column. That is what you should use in a <em>where</em> clause of a sql query to see all <span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModules</strong></span>&nbsp;that belong to a certain&nbsp;<span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>. Here is an example in the screenshot below for all <span style="color:#3366ff;background-color:#ffffff;"><strong>ProcessModules</strong></span>&nbsp;of the <strong>DWMaintenance</strong> <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>. These are not &quot;ordered&quot; in this result - if you want to figure out the &quot;order&quot; in which they would run, you need to check out the <strong>ModuleLevel</strong> column along with each dependency for each module which can be seen in the <span style="font-size:small;"><strong>Infra.ModuleTriggerCondition</strong></span> table.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/Infra.ProcessModule.jpg" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/Infra.ProcessModule.jpg"><img style="border-color:currentColor;" alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/Infra.ProcessModule.jpg" original-url="http://blogs.technet.com/resized-image.ashx/__size/943x277/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/Infra.ProcessModule.jpg" /></a></p>
<p></p>
<p><span style="font-size:medium;"><strong>4.</strong></span> The <span style="font-size:small;"><strong>Infra.</strong><span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span></span> table is where all the <span style="color:#339966;background-color:#ffffff;"><strong>Batches</strong></span> will be found (current/previous and next - check out <span style="font-size:small;"><strong>Infra.BatchHistory</strong></span> for a history of these). This is where you will be able to see the BatchIds for the&nbsp;<span style="color:#ff6600;background-color:#ffffff;"><strong>Processes</strong></span> and you can view them for a specific&nbsp;<span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span> by using the <strong>ProcessId</strong> in a sql <em>where</em> clause. In the example screenshot below, we can see the&nbsp;<span style="color:#339966;background-color:#ffffff;"><strong>Batches</strong></span> of the time the screenshot was taken for the <strong>Process</strong> with <strong>ProcessId</strong> = 1 (which in this case is the <strong>DWMaintenance</strong> <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>).</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/Infra.Batch.jpg" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/Infra.Batch.jpg"><img width="752" height="82" style="border-color:currentColor;" alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/Infra.Batch.jpg" original-url="http://blogs.technet.com/resized-image.ashx/__size/752x82/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/Infra.Batch.jpg" /></a></p>
<p></p>
<p><span style="font-size:medium;"><strong>5.</strong></span> The <span style="font-size:small;"><strong>Infra.</strong><span style="color:#993366;background-color:#ffffff;"><strong>WorkItem</strong></span></span> table is where all the&nbsp;<span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong></span> of a&nbsp;<span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span> will be found. The most important part here is that this table is where we can see any errors for failed&nbsp;<span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong></span> of a&nbsp;<span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span> (that is an instance of a certain <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>). In the screenshot below, an example of the <span style="color:#993366;background-color:#ffffff;"><strong>WorkItems</strong></span>&nbsp;of the <span style="color:#339966;background-color:#ffffff;"><strong>Batch</strong></span>&nbsp;with <strong>BatchId <em>3098</em></strong> that is an instance of the <strong>DWMaintenance</strong> <span style="color:#ff6600;background-color:#ffffff;"><strong>Process</strong></span>.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/Infra.WorkItem.jpg" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/Infra.WorkItem.jpg"><img width="943" height="319" style="border-color:currentColor;" alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/Infra.WorkItem.jpg" original-url="http://blogs.technet.com/resized-image.ashx/__size/943x319/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/Infra.WorkItem.jpg" /></a></p>
<p></p>
<p><span style="font-size:medium;"><strong>6.</strong></span> The&nbsp;<span style="color:#99cc00;font-size:small;"><strong>DeploySequence</strong></span> table where we have an entry for each <span style="color:#99cc00;"><strong>DeploySequence</strong></span>&nbsp;(so each MP that is or was deployed). You should know that in this&nbsp;process, a staging table is used which is called <strong>DeploySequenceStaging</strong> and if deployment finished and was successful, then this staging&nbsp;table should be <strong>*empty*.</strong>&nbsp;Here is a screenshot (not all results) of how this looks like.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/DeploySequence.jpg" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/DeploySequence.jpg"><img width="943" height="225" style="border-color:currentColor;" alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/DeploySequence.jpg" original-url="http://blogs.technet.com/resized-image.ashx/__size/943x225/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/DeploySequence.jpg" /></a></p>
<p></p>
<p><span style="font-size:medium;"><strong>7.</strong></span> The <span style="color:#808000;font-size:small;"><strong>DeployItems</strong></span>&nbsp;table where we store an entry for each <span style="color:#99cc00;"><strong>DeploySequence</strong></span>&nbsp;(so each MP that is or was deployed). You should know that in this&nbsp;process, a staging table is used which is called <strong>DeployItemStaging</strong> and if deployment finished and was successful, then this staging&nbsp;table should be <strong>*empty*.</strong>&nbsp;Here is a screenshot with the list of <span style="color:#808000;"><strong>DeployItems</strong></span> belonging to the <span style="color:#99cc00;"><strong>DeploySequence</strong></span>&nbsp;of the <em><strong>System.WorkItem.Incident.Library</strong></em>&nbsp;Management Pack.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/DeployItem.jpg" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/DeployItem.jpg"><img width="943" height="84" style="border-color:currentColor;" alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/DeployItem.jpg" original-url="http://blogs.technet.com/resized-image.ashx/__size/943x84/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/DeployItem.jpg" /></a></p>
<p></p>
<p>In addition to that, you can always use <strong><a title="SQL Server Profiler" href="http://msdn.microsoft.com/en-us/library/ms173799.aspx" target="_blank">SQL Server Profiler</a></strong> to get detailed information about what queries are being executed, details into different errors that might happen and of course having the queries, also a possibility of understanding the <strong>&quot;why&quot;</strong> behind them. The most useful column on which you can filter on is the <strong>ApplicationName</strong> column a the trace. These are the various application names used by the DW Jobs processing modules:</p>
<ul>
<li>DW Jobs scheduling, execution and processing: <em><strong>SC DAL--Orchestration</strong> </em>and <em><strong>SC DAL--SCDW</strong></em></li>
<li><strong>DWMaintenance</strong> job: <em><strong>SC DAL--Maintenance</strong></em></li>
<li><strong>MPSync</strong> job: <em><strong>SC DAL--MP Sync</strong></em></li>
<li><strong>Extract</strong> jobs: <em><strong>SC DAL--SCDW Extract Module</strong></em></li>
<li><strong>Transform</strong> job: <em><strong>SC DAL--SCDW Transform Module</strong></em></li>
<li><strong>Load</strong> jobs: <em><strong>SC DAL--SCDW Load Module</strong></em></li>
<li><strong>Cube</strong> related jobs: <em><strong>Microsoft SQL Server Analysis Services</strong> </em>(and general troubleshooting of SQL Analysis Services &ndash; Application event log and SQL Analysis Services tracing)</li>
</ul>
<p>A cool template I usually use for the SQL Profiler Trace which is in 99% of the cases enough, has these settings (events and columns):</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/SQLProfilerSettings.jpg" original-url="http://blogs.technet.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/SQLProfilerSettings.jpg"><img width="855" height="546" style="border-color:currentColor;" alt=" " src="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/00/94/18/SQLProfilerSettings.jpg" original-url="http://blogs.technet.com/resized-image.ashx/__size/855x546/__key/communityserver-blogs-components-weblogfiles/00-00-00-94-18/SQLProfilerSettings.jpg" /></a></p>
<p></p>
<p></p>
<p><span style="font-size:medium;background-color:#ffff00;"><strong>NOTE:</strong></span> Attached, you will also find a file (<span style="background-color:#00ff00;"><strong>DWJobs_sql_queries.sql</strong></span>) that contains (commented) useful sql queries which you can and should use when troubleshooting the DW Jobs.</p>
<p></p>
<p>Good hunting! :)</p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/TNBlogsFS/prod.evol.blogs.technet.com/telligent.evolution.components.attachments/01/9418/00/00/03/64/12/38/DWJobs_sql_queries.sql" original-url="http://blogs.technet.com/cfs-filesystemfile.ashx/__key/telligent-evolution-components-attachments/01-9418-00-00-03-64-12-38/DWJobs_5F00_sql_5F00_queries.sql">DWJobs_sql_queries.sql</a></p>]]></content:encoded>
    </item>
    <item>
      <title>Update Rollup 4 for System Center 2012 R2 - important update for the Service Manager Data Warehouse</title>
      <link>https://docs.microsoft.com/archive/blogs/mihai/update-rollup-4-for-system-center-2012-r2-important-update-for-the-service-manager-data-warehouse</link>
      <pubDate>Tue, 11 Nov 2014 02:01:00 GMT</pubDate>
      <dc:creator><![CDATA[Mihai Sarbulescu]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.technet.microsoft.com/mihai/2014/11/11/update-rollup-4-for-system-center-2012-r2-important-update-for-the-service-manager-data-warehouse/</guid>
      <description><![CDATA[So, Update Rollup 4 for System Center 2012 R2 is out as you might know...]]></description>
      <content:encoded><![CDATA[<p>So, Update Rollup 4 for System Center 2012 R2 is out as you might know :D</p>
<p><a title="UR4 for System Center 2012 R2" href="http://support.microsoft.com/kb/2992012" target="_blank">http://support.microsoft.com/kb/2992012</a></p>
<p></p>
<p>I encourage you to install UR4 for Service Manager because next to other&nbsp;fixes,&nbsp;there&#39;s a very important fix included here for the Data Warehouse.</p>
<p>This is part of the fixes and improvements we are trying to bring to the Data Warehouse: <a title="UR4 for System Center 2012 R2 - SvcMgr" href="http://support.microsoft.com/kb/2989601" target="_blank">http://support.microsoft.com/kb/2989601</a></p>
<p>Data Warehouse Transform jobs have a hardcoded 60-minute time-out. Therefore, Data Warehouse jobs cannot be disabled for very long because the volume of data to be transformed can quickly pile up. This can cause an issue if the volume exceeds the amount that can be processed by the transform modules within the time-out period.</p>
<p>This fix included in UR4 has 2 parts: an improvement of an involved stored procedure which makes it be able to run faster + a new registry setting that can be created to be able to control the default timeout for the command, as well as changing the default from 60 to 180 seconds.</p>
<p></p>
<p>Happy updating! :D</p>
<p></p>
<p></p>]]></content:encoded>
    </item>
  </channel>
</rss>