Case of the Black Background Window (.NET Patching)

On Windows XP  a Windows form had a white background, something like this:


However on Windows 8 it had a black background like this, making text on the form unreadable:



This is a common AppCompat bug…where the developer instead of selecting “White” to make a Windows form background, selected Active Caption Text.


This is a change from the default Control


If the source code is not available/developer can’t patch it, there are a few ways we can fix this. We can change Active Title Bar colour back to White on a Windows 7 machine, save it as a .themepack and apply it to Windows 8 or later.




Patching .NET EXE directly:

1) Open EXE in ILDasm and click File –> Dump then select the default settings. ILDasm is found in the Windows SDK, it will be in a folder similar to C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools\

2) Open the .IL file in a text editor and search replace





Typically you will only want to replace those that just precede a set_BackColor

call       valuetype [System.Drawing]System.Drawing.Color [System.Drawing]System.Drawing.SystemColors::get_ActiveCaptionText()
callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Control::set_BackColor(valuetype [System.Drawing]System.Drawing.Color)


call       valuetype [System.Drawing]System.Drawing.Color [System.Drawing]System.Drawing.SystemColors::get_Control()
callvirt   instance void [System.Windows.Forms]System.Windows.Forms.Control::set_BackColor(valuetype [System.Drawing]System.Drawing.Color)


3) We then recompile the EXE, using ilasm which lives in the .NET framework directories, specifying the IL file and the .RES file output from ILDASM


c:\windows\\Framework\v2.0.50727\ilasm /RESOURCE=WorkflowApplication.res

4) You program should now be fixed!

For more patching examples refer to

Posted in .NET, AppCompat, IL, Patching | Leave a comment

Case of the Invoked Hang (.NET)

A .NET application was hanging completely when certain background tasks were occurring. Using ProcDump ( ) with option Procdump –ma <process name> i captured a 3 dump files about 10 seconds apart, to identify where hang was occurring.

Opening dmp file in WinDbg with SOS extension:

.loadby sos clr

The UI thread

0:000> kv
# ChildEBP RetAddr  Args to Child             
00 006df114 754d1286 00000001 00a3cc10 00000001 ntdll!NtWaitForMultipleObjects+0xc (FPO: [5,0,0])
01 006df2a8 6913b957 00000001 00a3cc10 00000000 KERNELBASE!WaitForMultipleObjectsEx+0x136 (FPO: [SEH])
02 006df2f8 6913b62c 00000000 ffffffff 00000001 clr!WaitForMultipleObjectsEx_SO_TOLERANT+0x3c (FPO: [Non-Fpo])
03 006df384 6913b71d 00000001 00a3cc10 00000000 clr!Thread::DoAppropriateWaitWorker+0x237 (FPO: [5,25,0])
04 006df3f0 6913b8fd 00000001 00a3cc10 00000000 clr!Thread::DoAppropriateWait+0x64 (FPO: [Non-Fpo])
05 006df43c 6913b0d2 ffffffff 00000001 00000000 clr!CLREventBase::WaitEx+0x128 (FPO: [Non-Fpo])
06 006df450 6910134d ffffffff 00000001 00000000 clr!CLREventBase::Wait+0x1a (FPO: [3,0,0])
07 006df4b4 69241bb8 00010000 006df4d8 352bbf87 clr!CLREventWaitWithTry+0x42 (FPO: [Non-Fpo])
08 006df4ec 69125dde 352bbe77 027f9cd8 00000000 clr!ThreadStore::WaitForOtherThreads+0x74 (FPO: [Non-Fpo])
09 006df51c 691247b7 352bbe43 00aecab8 00aa77d0 clr!RunMain+0x26d (FPO: [Non-Fpo])
0a 006df788 69124dbb 00000000 352bbcf3 00540000 clr!Assembly::ExecuteMainMethod+0x144 (FPO: [1,149,0])
0b 006dfc90 69124e61 352bb783 00000000 00000000 clr!SystemDomain::ExecuteMainMethod+0x651 (FPO: [0,315,0])
0c 006dfce8 69124662 352bb643 00000000 00000000 clr!ExecuteEXE+0x4c (FPO: [Non-Fpo])
0d 006dfd28 690e4e91 352bb60f 00000000 00000000 clr!_CorExeMainInternal+0xdc (FPO: [Non-Fpo])
0e 006dfd64 6a10cd87 334078bd 6a18dc60 6a10cd16 clr!_CorExeMain+0x4d (FPO: [Non-Fpo])
0f 006dfda0 6a18dd05 6a18dc60 639b32df 006dfdc4 mscoreei!_CorExeMain+0x10a (FPO: [0,10,4])
10 006dfdb0 74d33744 7ec9f000 74d33720 12f4615d mscoree!_CorExeMain_Exported+0xa5 (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
11 006dfdc4 779ca064 7ec9f000 ad1ace76 00000000 kernel32!BaseThreadInitThunk+0x24
12 006dfe0c 779ca02f ffffffff 779ed7de 00000000 ntdll!__RtlUserThreadStart+0x2f (FPO: [Non-Fpo])
13 006dfe1c 00000000 6a18dc60 7ec9f000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

I took a quick look at the .NET stack traces




Thread  21
Current frame: ntdll!NtWaitForSingleObject+0xc
ChildEBP RetAddr  Caller, Callee
0099e3a0 754c8d09 KERNELBASE!WaitForSingleObjectEx+0x99, calling ntdll!NtWaitForSingleObject
0099e414 68fc1bb7 clr!CLREventBase::Reset+0x145
0099e444 68fc1bfe clr!CLREventBase::Reset+0x18d, calling clr!CLREventBase::Reset+0x114
0099e494 68fc1b81 clr!CLREventBase::WaitEx+0x152, calling clr!CLREventBase::Reset+0x163
0099e4b8 756fcca6 combase!WindowsCreateString+0x6886, calling msvcrt!memcmp
0099e4cc 6913b0d2 clr!CLREventBase::Wait+0x1a, calling clr!CLREventBase::WaitEx
0099e4e4 69244395 clr!Thread::WaitSuspendEventsHelper+0x8a, calling clr!CLREventBase::Wait
0099e524 690533c5 clr!SafeReleasePreemp+0x234
0099e550 69244468 clr!Thread::WaitSuspendEvents+0x14, calling clr!Thread::WaitSuspendEventsHelper
0099e564 692427cc clr!Thread::RareEnablePreemptiveGC+0x8e, calling clr!Thread::WaitSuspendEvents
0099e57c 69137d3b clr!Thread::RareDisablePreemptiveGC+0x102, calling clr!Thread::RareEnablePreemptiveGC
0099e5cc 6913b694 clr!Thread::DoAppropriateWaitWorker+0x3cb, calling clr!GCCoopHackNoThread::~GCCoopHackNoThread
0099e648 6913b71d clr!Thread::DoAppropriateWait+0x64, calling clr!Thread::DoAppropriateWaitWorker
0099e69c 690bb01e clr!AcquireSafeHandle+0x33, calling clr!_EH_epilog3
0099e6b4 690bb130 clr!WaitHandleNative::CorWaitOneNative+0x163, calling clr!Thread::DoAppropriateWait
0099e72c 690bb06d clr!WaitHandleNative::CorWaitOneNative+0x4c, calling clr!LazyMachStateCaptureState
0099e750 68fb278a clr!HelperMethodFrame::Push+0x10, calling clr!GetThread
0099e758 69068141 clr!AppDomainNative::IsFinalizingForUnload+0x3a, calling clr!_EH_epilog3
0099e7bc 680cc7c1 (MethodDesc 67e4df10 +0x21 System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle, Int64, Boolean, Boolean)), calling clr!WaitHandleNative::CorWaitOneNative
0099e7d0 680cc788 (MethodDesc 67e4dedc +0x28 System.Threading.WaitHandle.WaitOne(Int32, Boolean)), calling (MethodDesc 67e4df10 +0 System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle, Int64, Boolean, Boolean))
0099e7ec 0085bb9d (MethodDesc 04feadb8 +0x1a5 System.Windows.Forms.Control.WaitForWaitHandle(System.Threading.WaitHandle))
0099e7f4 68fb21a6 clr!JIT_MonExitWorker+0xa, calling clr!GetThread
0099e830 0949b3e3 (MethodDesc 04feb6f4 +0x2cb System.Windows.Forms.Control.MarshaledInvoke(System.Windows.Forms.Control, System.Delegate, System.Object[], Boolean)), calling 0949a078
0099e8ac 0085b5fb (MethodDesc 04feb648 +0x4b System.Windows.Forms.Control.Invoke(System.Delegate, System.Object[])), calling 0949a038
0099e8e8 0085b598 (MethodDesc 04feb63c +0x8 System.Windows.Forms.Control.Invoke(System.Delegate)), calling (MethodDesc 04feb648 +0 System.Windows.Forms.Control.Invoke(System.Delegate, System.Object[]))
0099e8f0 0085b3af (MethodDesc 059f56c8 +0x1c7 Main.Form1.bulkWorker_DoWork(System.Object, System.ComponentModel.DoWorkEventArgs)), calling 0085ae0c


This is a common cause of .NET application hang – .Invoke called from background thread. This is easily fixed by replaced .Invoke with .BeginInvoke


What if there is no source code, vendor is slow to fix, etc? You can patch it yourself, at your own risk…

Use ILDasm ( ) to dump the contents to IL format

Do a search replace from

callvirt   instance object [System.Windows.Forms]System.Windows.Forms.Control::Invoke


callvirt   instance class [mscorlib]System.IAsyncResult [System.Windows.Forms]System.Windows.Forms.Control::BeginInvoke

We then recompile:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe /RESOURCE=Program.res

  And the hangs are gone…

What is the difference between Invoke & BeginInvoke:

  • Invoke: Executes the specified delegate on the thread that owns the control’s underlying window handle.
  • BeginInvoke: Executes the specified delegate on the thread that owns the control’s underlying window handle.

Some of the problems with using invoke:

  • Causes thread to wait on another thread, increases risk of deadlock in your application. Using ThreadPools may help, but under high load in “threadpool starvation” the deadlock may be triggered.
  • Invoke forces thread switch immediately that has potential to decrease application stability
  • Each Invoke requires a separate thread switch, potentially impacting application performance

Some advantage of BeginInvoke:

  • Multiple BeginInvoke can be executed in a single thread switch ‘
  • Schedules execution of delegate on other thread – thread switch occurs “when OS is ready”

However a word of caution

Invoke is required when synchronous execution is expected. If code relying on changes made by BeginInvoke immediately follows in a separate code block, you may have another issue.


SomeControl.BeginInvoke(new Action(delegate {

  SomeControl.Text=”some value”


// trying to read SomeControl.Text here is not safe, may not get expected result – move code reyling on BeginInvoke’s result into BeginInvoke or use Invoke

Posted in .NET, Debugging, IL, WinDbg | Tagged | Leave a comment

Case of the Skype for Business 2015 “Operating System is not presently configured to run this application”

On Windows 10 build 10162 after installing Office 2016 Skype for Business started throwing the error: The operating system is not presently configured to run this application.


Using Task Manager I right clicked lync.exe and created a dump file.

Opening in WinDbg using ~k I found the thread 4 was displaying the dialog box, and set the context to that thread using ~4s

As the dmp file was 32-bit process captured with 64-bit task manager  I set to 32 bit context

.load wow64exts


Looking at the stack:

0:004:x86> kv
# ChildEBP RetAddr  Args to Child             
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0503c928 75adbed2 00000000 00000000 00000000 user32!WaitMessage+0xc
01 0503c958 75b2e6a6 00000000 75b2c560 0503cba0 user32!GetCapture+0x122
02 0503ca24 75b2d58a 0503cba0 1a0bcf90 00000000 user32!SoftModalMessageBox+0xea6
03 0503cb88 75b2d2ac 1a0bcf90 00000000 00000000 user32!MessageBoxW+0x2ba
04 0503cc08 75b2d20b 00000000 1a0bcf90 00000000 user32!MessageBoxTimeoutW+0x6c
05 0503cc3c 75b2cfeb 00000000 1a07d200 00000000 user32!MessageBoxTimeoutA+0x7b
06 0503cc5c 75b2cfb8 00000000 1a07d200 00000000 user32!MessageBoxExA+0x1b
07 0503cc78 559ca7b6 00000000 1a07d200 00000000 user32!MessageBoxA+0x18
08 0503cc98 557c3fcd 0503ccb4 55685c96 00000001 OLMAPI32_55680000!Validate_SetValidationFlags+0x79a0
09 0503cca0 55685c96 00000001 55a99db0 55aaab94 OLMAPI32_55680000!ShutdownEDPSessionProtector+0x5ebe4
0a 0503ccb4 55685c66 00000001 0503cd0c 00000000 OLMAPI32_55680000!ReadRegDWordValueAndPolicy+0x45d
0b 0503cccc 55685cbb 55a1ecd0 00000001 0503cd0c OLMAPI32_55680000!ReadRegDWordValueAndPolicy+0x42d
0c 0503cce8 556848b4 00000001 0503cd0c 00000001 OLMAPI32_55680000!ReadRegDWordValueAndPolicy+0x482
0d 0503cd3c 55685c4d 55a99a7c 55aa18e4 00000000 OLMAPI32_55680000!FIsMsoAuthEnabled+0x325a
0e 0503cd80 556853d7 55680000 00000001 00000000 OLMAPI32_55680000!ReadRegDWordValueAndPolicy+0x414
0f 0503cda4 55681143 55680000 00000001 00000000 OLMAPI32_55680000!FIsMsoAuthEnabled+0x3d7d
10 0503cde4 55681017 55680000 00000001 00000000 OLMAPI32_55680000+0x1143
11 0503cdf8 77d88b4e 55680000 00000001 00000000 OLMAPI32_55680000+0x1017
12 0503ce18 77d5652b 55681000 55680000 00000001 ntdll_77d20000!RtlQueryUnbiasedInterruptTime+0x33e
13 0503ce68 77d5432f 00000001 00000000 e5ee6e3b ntdll_77d20000!LdrShutdownThread+0x29b
14 0503cee8 77d54128 1a0b05b8 00000000 0503cfa4 ntdll_77d20000!LdrGetDllHandleByName+0x56f
15 0503cf0c 77d53949 0503cf27 0503cfa8 0503cfa4 ntdll_77d20000!LdrGetDllHandleByName+0x368
16 0503cf28 77d55b30 e5ee6fa3 0503d0e8 0503d178 ntdll_77d20000!LdrShutdownProcess+0x949
17 0503cf70 77d65ec4 00000600 00000004 00000000 ntdll_77d20000!RtlCreateUnicodeStringFromAsciiz+0x6f0
18 0503d0bc 77d68475 00000000 00000001 0503d0e0 ntdll_77d20000!ApiSetQueryApiSetPresence+0x124
19 0503d140 76834248 00000009 0503d168 0503d178 ntdll_77d20000!LdrLoadDll+0x75
1a 0503d180 75e60a3c 0503d228 00000000 00000008 KERNELBASE!LoadLibraryExW+0x138
1b 0503d1a4 75e609b7 00000008 0503d1f8 0503d228 combase!GetHGlobalFromStream+0x55c
1c 0503d1c8 75e607db 0503d1f4 0503d1f0 0503d1f8 combase!GetHGlobalFromStream+0x4d7
1d 0503d204 75e62b6d 0503d224 75f85208 80004005 combase!GetHGlobalFromStream+0x2fb
1e 0503d454 75eaff4f 00000001 0503d7cc 0503d4bc combase!CLSIDFromString+0x110d
1f 0503d784 75e64d22 0503d7ac e25cfd03 0503d7b8 combase!CoCreateInstance+0x1ecf
20 0503d7b8 75e64f6c 0503de74 75e64e40 00000000 combase!RoActivateInstance+0xc32
21 0503d828 75e684fa 75f85c34 00000000 0503de74 combase!RoActivateInstance+0xe7c
22 0503d874 75e65522 0503de74 00000000 0503e510 combase!RoActivateInstance+0x440a
23 0503d8cc 75e658e5 75f85c38 00000000 0503de74 combase!RoActivateInstance+0x1432
24 0503d8fc 75e65860 75f85c30 00000001 00000000 combase!RoActivateInstance+0x17f5
25 0503d920 75e65b5b 75f85c30 0503dca0 00000000 combase!RoActivateInstance+0x1770
26 0503d960 75e659d7 75f85c30 0503dca0 00000000 combase!RoActivateInstance+0x1a6b
27 0503d990 75e684db 75f85c30 00000000 0503de74 combase!RoActivateInstance+0x18e7
28 0503d9dc 75e667fd 0503de74 00000000 0503e510 combase!RoActivateInstance+0x43eb
29 0503dc40 75e684e2 75f85c2c 00000000 0503de74 combase!RoActivateInstance+0x270d
2a 0503dc8c 75ead106 0503de74 00000000 0503e510 combase!RoActivateInstance+0x43f2
2b 0503e608 75eac379 00000003 00000000 00000001 combase!RoGetActivationFactory+0x68b6
2c 0503e650 75eae1b2 00000003 00000000 00000001 combase!RoGetActivationFactory+0x5b29
2d 0503e688 604edfbd 605770f8 00000000 00000003 combase!CoCreateInstance+0x132
2e 0503e710 605159c4 605770f8 00000000 00000003 OLMAPI32!HrGetCrawlScopeManagerWrapper+0x26aa
2f 0503e738 60515958 1154cfb0 0503e774 00000001 OLMAPI32!HrGetAcctManagerFromSession+0x35
30 0503e75c 56e4beb6 113c8440 0503e774 0503ee88 OLMAPI32!HrGetAcctManager+0x62
31 0503e778 56e4b817 1a0b4f60 00000104 114139b8 MSPST32!OSTServiceEntry+0x32d69
32 0503edac 56e12f1c 114139b8 1a0bc1d8 00000000 MSPST32!OSTServiceEntry+0x326ca
33 0503f2e8 56fcf503 114139b8 113c8440 00000000 MSPST32!MSProviderInit+0xc8b
34 0503f3bc 56fc3feb 113e6388 1a0b2290 113c8440 EMSMDB32!MSProviderInit+0x14445
35 0503f560 56fc3975 113e6388 113c8440 00000000 EMSMDB32!MSProviderInit+0x8f2d
36 0503f5a0 604eb519 113e6388 113c8440 00000000 EMSMDB32!MSProviderInit+0x88b7
37 0503f5e0 604eb2a0 0503f71c 114c71a8 9000009c OLMAPI32!HrCreateConnectionManager+0x47d7
38 0503f634 604eb111 00000000 114e9240 0503f6c0 OLMAPI32!HrCreateConnectionManager+0x455e
39 0503f674 604e9dac 0503f71c 0503f6c0 63bf1bf4 OLMAPI32!HrCreateConnectionManager+0x43cf
3a 0503f700 604e95be 0503f71c afaaf001 114e9150 OLMAPI32!HrCreateConnectionManager+0x306a
3b 0503f7a4 604e951d 1154cfb0 00000000 00000082 OLMAPI32!HrCreateConnectionManager+0x287c
3c 0503f7ec 639ea99a 1154cfb0 00000000 00000082 OLMAPI32!HrCreateConnectionManager+0x27db
3d 0503f860 639e9e32 0503f8a0 00000000 0503f8b4 MSO!Ordinal2928+0x2676
3e 0503f870 639f7508 0503f8a0 afa3272b 114c6ba8 MSO!Ordinal2928+0x1b0e
3f 0503f8b4 639f74a7 1123b590 00000000 0503f900 MSO!Ordinal7732+0x21c1
40 0503f8f0 639c3747 00000000 00995f08 00000000 MSO!Ordinal7732+0x2160
41 0503f934 639c3611 11547048 00995f08 0503f95c MSO!Ordinal2317+0x7e7
42 0503f944 639c357d 11547050 114dd598 11547050 MSO!Ordinal2317+0x6b1
43 0503f95c 636fbc0d 11547050 114dd598 636ecb7f MSO!Ordinal2317+0x61d
44 0503f98c 636ebab1 0503f9fc 0503f9e0 00950af8 MSO!Ordinal1788+0x4c3
45 0503f9a4 636e9422 0503f9fc 636e8690 00950af8 MSO!Ordinal1978+0xfc
46 0503f9d8 636e86e9 00000000 636e86e9 0503f9fc MSO!Ordinal1981+0x1cdd
47 0503fa2c 75703774 00950af8 75703750 f0a53cda MSO!Ordinal1981+0xfa4
48 0503fa40 77d790d1 00950af8 e5ee5a5b 00000000 kernel32!BaseThreadInitThunk+0x24
49 0503fa88 77d7909c ffffffff 77d9d77f 00000000 ntdll_77d20000!RtlWalkFrameChain+0x141
4a 0503fa98 00000000 636e8690 00950af8 00000000 ntdll_77d20000!RtlWalkFrameChain+0x10c
0:004:x86> da 1a07d200
1a07d200  “The operating system is not pres”
1a07d220  “ently configured to run this app”
1a07d240  “lication…”
0:004:x86> du 0503d228
0503d228  “C:\Program Files (x86)\Microsoft”
0503d268  ” Office\root\Office16\OLMAPI32.D”
0503d2a8  “LL”
0:004:x86> lmvm olmapi32
Browse full module list
start             end                 module name
604c0000 608a4000   OLMAPI32   (export symbols)       OLMAPI32.DLL
    Loaded symbol image file: OLMAPI32.DLL
    Image path: C:\Program Files (x86)\Microsoft Office\Office15\OLMAPI32.DLL
    Image name: OLMAPI32.DLL
    Browse all global symbols  functions  data
    Timestamp:        Wed May 13 01:23:36 2015 (55521AF8)
    CheckSum:         003F08B5
    ImageSize:        003E4000
    File version:     15.0.4727.1000
    Product version:  15.0.4727.0
    File flags:       0 (Mask 3F)
    File OS:          40004 NT Win32
    File type:        0.0 Unknown
    File date:        00000000.00000000
    Translations:     0000.04e4
    CompanyName:      Microsoft Corporation
    ProductName:      MAPI32
    InternalName:     MAPI32.DLL
    OriginalFilename: MAPI32.DLL
    ProductVersion:   15.0.4727.1000
    FileVersion:      15.0.4727.1000
    FileDescription:  Extended MAPI 1.0 for Windows NT
0:004:x86> lmvm lync
Browse full module list
start             end                 module name
00ee0000 025d8000   lync       (export symbols)       lync.exe
    Loaded symbol image file: lync.exe
    Image path: C:\Program Files (x86)\Microsoft Office\Office15\lync.exe
    Image name: lync.exe
    Browse all global symbols  functions  data
    Timestamp:        Tue May 19 19:02:46 2015 (555AFC36)
    CheckSum:         01702E87
    ImageSize:        016F8000
    File version:     15.0.4727.1001
    Product version:  15.0.4727.0
    File flags:       0 (Mask 3F)
    File OS:          40004 NT Win32
    File type:        1.0 App
    File date:        00000000.00000000
    Translations:     0000.04e4
    CompanyName:      Microsoft Corporation
    ProductName:      Microsoft Office 2013
    InternalName:     Lync
    OriginalFilename: Lync.exe
    ProductVersion:   15.0.4727.1001
    FileVersion:      15.0.4727.1001
    FileDescription:  Skype for Business

0:004:x86> lmvm OLMAPI32_55680000
Browse full module list
start             end                 module name
55680000 55b0b000   OLMAPI32_55680000   (export symbols)       OLMAPI32.DLL
    Loaded symbol image file: OLMAPI32.DLL
    Image path: C:\Program Files (x86)\Microsoft Office\root\Office16\OLMAPI32.DLL
    Image name: OLMAPI32.DLL
    Browse all global symbols  functions  data
    Timestamp:        Sat Jul 04 21:31:40 2015 (5597C41C)
    CheckSum:         004853C4
    ImageSize:        0048B000
    File version:     16.0.4229.1002
    Product version:  16.0.4229.0
    File flags:       22 (Mask 3F) Pre-release Special
    File OS:          40004 NT Win32
    File type:        0.0 Unknown
    File date:        00000000.00000000
    Translations:     0000.04e4
    CompanyName:      Microsoft Corporation
    ProductName:      MAPI32
    InternalName:     MAPI32.DLL
    OriginalFilename: MAPI32.DLL
    ProductVersion:   16.0.4229.1002
    FileVersion:      16.0.4229.1002
    FileDescription:  Extended MAPI 1.0 for Windows NT


So in the stack trace we have two different versions of OLMAPI32.dll – v15 pre-release v16.

We can easily see it gets loaded when using ProcMon and filtering Details Contains OLMAPI32.dll from this registry key:



However if Skype For Business 2015 and Outlook 2016 are closed, and opened in the following order,Skype launches correctly.

1) Outlook 2016

2) Skype For Business 2015

In this scenario only the v15 version of DLL gets loaded:



After several launches of Outlook 2016 & Lync, the problem went away.

Posted in Click2Run, Office, WinDbg, Windows 10 | Tagged | Leave a comment

Windows 10 Build Upgrades Break VMWare Workstation Network

Every Windows 10 build upgrade breaks network access in VMWare Workstation Virtual machines.

This is fixed by ensuring all VMs are suspended/shutdown then clicking Edit | Virtual Network Editor…


Selecting Change Settings


Then Restore Defaults



But why is it breaking?

This restore defaults reconfigures a number of registry & file locations, including:

  • HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap
  • HKLM\SOFTWARE\Wow6432Node\VMware, Inc.\VMnetLib\VMnetConfig
  • HKLM\System\CurrentControlSet\Services\VMnetDHCP
  • HKLM\System\CurrentControlSet\Services\EventLog\System\VMnetDHCP
  • HKLM\System\CurrentControlSet\Enum\ROOT\VMWARE
  • %ProgramData%\VMware\vmnetdhcp.conf
  • %ProgramData%\VMWare\vmnetdhcp.leases
  • %ProgramData%\VMWare\netmap.conf

After a new Windows 10 build has been installed via Windows Update these keys are missing:

  • HKLM\SYSTEM\CurrentControlSet\Services\VMnetDHCP
  • HKLM\SYSTEM\CurrentControlSet\Services\VMware NAT Service

The VMWare DHCP and NAT services have disappeared. To fix it automatically we can just need to restore the services, and the related registry settings:

In my case I used had exported these settings from when VMWare was working in file called settings.reg

Windows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VMware NAT Service] "Type"=dword:00000010 "Start"=dword:00000002 "ErrorControl"=dword:00000001 "ImagePath"=hex(2):43,00,3a,00,5c,00,57,00,49,00,4e,00,44,00,4f,00,57,00,53,00,\ 5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,76,00,6d,00,6e,\ 00,61,00,74,00,2e,00,65,00,78,00,65,00,00,00 "DisplayName"="VMware NAT Service" "DependOnService"=hex(7):56,00,4d,00,6e,00,65,00,74,00,75,00,73,00,65,00,72,00,\ 69,00,66,00,00,00,00,00 "WOW64"=dword:00000001 "ObjectName"="LocalSystem" "Description"="Network address translation for virtual networks." "FailureActions"=hex:58,02,00,00,00,00,00,00,00,00,00,00,03,00,00,00,14,00,00,\ 00,01,00,00,00,e8,03,00,00,01,00,00,00,e8,03,00,00,00,00,00,00,04,00,00,00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VMware NAT Service\Parameters] "ConfigPath"=hex(2):43,00,3a,00,5c,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,\ 00,44,00,61,00,74,00,61,00,5c,00,56,00,4d,00,77,00,61,00,72,00,65,00,5c,00,\ 00,00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VMnetDHCP] "Type"=dword:00000010 "Start"=dword:00000002 "ErrorControl"=dword:00000001 "ImagePath"=hex(2):43,00,3a,00,5c,00,57,00,49,00,4e,00,44,00,4f,00,57,00,53,00,\ 5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,76,00,6d,00,6e,\ 00,65,00,74,00,64,00,68,00,63,00,70,00,2e,00,65,00,78,00,65,00,00,00 "DisplayName"="VMWare DHCP Service" "DependOnService"=hex(7):56,00,4d,00,6e,00,65,00,74,00,75,00,73,00,65,00,72,00,\ 69,00,66,00,00,00,00,00 "ObjectName"="LocalSystem" "WOW64"=dword:00000001 "Description"="DHCP service for virtual networks." "DeleteFlag"=dword:00000001 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VMnetDHCP\Parameters] "ConfFile"=hex(2):43,00,3a,00,5c,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,\ 44,00,61,00,74,00,61,00,5c,00,56,00,4d,00,77,00,61,00,72,00,65,00,5c,00,76,\ 00,6d,00,6e,00,65,00,74,00,64,00,68,00,63,00,70,00,2e,00,63,00,6f,00,6e,00,\ 66,00,00,00 "LeaseFile"=hex(2):43,00,3a,00,5c,00,50,00,72,00,6f,00,67,00,72,00,61,00,6d,00,\ 44,00,61,00,74,00,61,00,5c,00,56,00,4d,00,77,00,61,00,72,00,65,00,5c,00,76,\ 00,6d,00,6e,00,65,00,74,00,64,00,68,00,63,00,70,00,2e,00,6c,00,65,00,61,00,\ 73,00,65,00,73,00,00,00 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VMnetDHCP\Parameters\VirtualEthernetSegments] [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VMnetDHCP\Parameters\VirtualEthernetSegments\1] "ListenTo"=dword:00000001 "HostIpAddress"=dword:01f8a8c0 [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\VMnetDHCP\Parameters\VirtualEthernetSegments\8] "ListenTo"=dword:00000001 "HostIpAddress"=dword:0199a8c0

Then ran the following commands:

sc create VMnetDHCP type= own start= auto binPath= C:\WINDOWS\system32\vmnetdhcp.exe DisplayName= "VMWare DHCP Service" depend= VMnetuserif sc create "VMWare NAT Service" type= own start= auto binPath= C:\WINDOWS\system32\vmnat.exe DisplayName= "VMWare NAT Service" depend= VMnetuserif reg import settings.reg net start VMnetDHCP net start "VMWare DHCP Service"

The services may fail to start if registry settings are not correct.

If when you try to start these services you get error 2: File Not Found, then copy vmnetdhcp.exe and vmnat.exe from C:\Program Files (x86)\VMware\VMware Workstation to C:\Windows\System32

When the next Windows 10 build comes down I will look into why these keys get removed, if the issue is not fixed by then.

Posted in VMWare, Windows 10 | Tagged | Leave a comment

Case of the Slow PowerShell Logon Script

A logon script was taking 30-40 seconds to run at logon.

$domain = "contoso" $Searcher = New-Object System.DirectoryServices.DirectorySearcher("domain",$domain) $Searcher.Filter = ("(sAMAccountName=$env:username)") $user=$searcher.FindOne() $ugroups=$User.GetDirectoryEntry().memberOf $ugroups -split '=,' | ForEach-Object { $Searcher.Filter = ("(distinguishedName=$_)") $groups=$searcher.FineOne() $nested=$groups.GetDirectoryEntry().memberOf if($nested -like "CN=*") { $ugroups = $ugroups + " " + $nested } } $ugroups -split '=,' | ForEach-Object { if ($_ -Like "CN=Group_Prefix_*") { $Searcher.Filter = ("(distinguishedName=$_)") $fgroups=$searcher.FindAll() ForEach ($group in $fgroups) { $info=$group.GetDirectoryEntry().info $url=$group.GetDirectoryEntry().url $att3=$group.GetDirectoryEntry().ExtensionAttribute3 $att4=$group.GetDirectoryEntry().ExtensionAttribute4 $att5=$group.GetDirectoryEntry().ExtensionAttribute5 # do something with the values } } }


Some flaws in this script:

  • Searching Active Directory to find current user’s group membership, this is unnecessary.
  • Once Distinguished Names (DNs) for Groups were obtained, instead of opening them directly, they are split up to find the Group Name, and AD is searched again, for every single group the user is a member of.

The optimised script ran in under 1 second. This performs 0 Active Directory searches, and so avoids the potentially expensive operation. It takes advantage of the fact all groups are in a known OU, so they can be opened directly using New-Object System.DirectoryServices.DirectoryEntry.

In the updated script we retrieve user’s groups from System.Security.Principal.WindowsPrincipal for the logged on user, this is almost instant. In addition one we have the Group Distinguished name, in format LDAP://CN=Name,OU=Some OU,DC=domain,DC=COM” we access the object directly with  $de = New-Object System.DirectoryServices.DirectoryEntry($groupDN)

This updated script does have some limitation:

  • The group membership will only update at user logon – which is OK because this script only runs at logon
  • If you are going to use special characters like commas in your group names, the script will need to be updated with necessary escape codes for DN format
#groups will always be in this OU $groupOU = "OU=Groups,DC=contoso,DC=local" $currentUser = [Security.Principal.WindowsIdentity]::GetCurrent() $WindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($currentUser) $groups = $WindowsPrincipal.Identity.Groups| Foreach-Object { $_.Translate([Security.Principal.NTAccount]) } ForEach ($group in $groups) { if ($group.Value.Contains("\")) { $domain = $group.Value.Split("\")[0] $groupName = $group.Value.Split("\")[1] if ($groupName.StartsWith("Group_Prefix")) { $groupDN = [string]::Format("LDAP://CN={0},{1}",$groupName,$groupOu) $de = New-Object System.DirectoryServices.DirectoryEntry($groupDN) $info=$ $url=$de.url $att3=$de.ExtensionAttribute3 $att4=$de.ExtensionAttribute4 $att5=$de.ExtensionAttribute5 # do something with the values } } }

Posted in Performance, PowerShell, Scripting | Tagged | Leave a comment

Performance Analysis Tool (PAL) PerfMon Templates Don’t Load in Win10

Using Performance Analysis Tool ( on Windows 10 build 10130 I had exported a PerfMon template for Calculated Disk IOPS:



However when attempting to import into PerfMon on Windows 10 the Next and Finish buttons are disabled.



If we hit “Back” arrow, then forward again, the Finish button is enabled, but clicking it results in error:

When attempting to create the Data Collector Set the following system error occurred:
Not enough storage is available to complete this operation.


Using Rohitab API Monitor with Windows Application UI Development monitoring on, I attached ApiMonitor to mmc.exe process hosting PerfMon.msc just before I imported the template.


We find this function call:

#    Time of Day    Thread    Module    API    Return Value    Error    Duration
636128    2:00:46.910 PM    3    PLA.dll    LoadStringW ( 0x00007ffeb0bf0000, 10027, 0x000000000904b200, 1024 )    0    0 = The operation completed successfully.     0.0000226



Looking at MSDN documentation for LoadString we can see it returns 0 if the resource does not exist.

Using a simple test script  based on the one here

We can on Server 2008 R2 the values are there:


However on Windows 10 :


Dumping all resource strings in the DLL, we find in Windows 10, these strings are no longer present at all.

Sample script here:!28213&authkey=!AGecn7l_8oE95uU&ithint=file%2czip

So we changed the XML file to have a blank description.





Now it imports fine…

Posted in AppCompat, PerfMon, Windows 10 | Tagged | 3 Comments

Retrieving COM Class Factory For Component Failed 800700c1

A customer had migrated from 32-bit Windows XP to 64-bit Windows 8 and many of their .NET apps failed to launch, with an error like below:


The registry key for HKCR\CLSID\<GUID> was present, and the relevant OCX/DLL had been registered and was present on the system.

When you see error 800700c1 typically the issue is you have a 64-bit EXE trying to load a 32-bit DLL, which is not possible in Windows.

This issue is typically unique to .NET applications that also load native DLLs, because they can be compiled to “ANY CPU”

We should check the .NET exe with with CorFlags ( )

This tool is available from the Windows SDK in the .NET Development Tools subcomponent (Developer Tools -> Windows Development Tools -> .NET Development Tools)


We can see with 32bitreq = 0, this is set to “ANY CPU” This means it will run as 64-bit EXE on Windows x64 and 32-bit EXE on 32-bit Windows. As a consequence

  • Any native DLLs it loads must be 64-bit
  • Any installer that installs reg keys must be marked as 64-bit so reg keys go to correct location

If the application needs/benefits from addressing more than 2GB of RAM then it may be best to leave it as “Any CPU” However then 64-bit versions of all DLLs it loads need to be installed/registered.

The easiest way to fix such an application is to change app to x86.

This can be done with compiler options in Visual Studio


Or the EXE can be modified using corflags.exe

For example:

corflags /32bit+ C:\source\wds\wds.exe

Now the EXE will run in 32-bit mode, even on x64 OS.


Posted in .NET | Tagged | Leave a comment