Category Archives: Scripting

Test-MailFlow cmdlet failing with *FAILURE*

I recently started looking into using the Test-Mailflow cmdlet to develop an email flow monitoring script in LogicMonitor. I had never tried using it in my current environment before and when I tried executing the cmdlet it just timed out with this output:

[PS] C:\Windows\system32>Test-Mailflow -Identity mailbox01
RunspaceId : 808205bb-e671-4a65-94ca-1828bf0f7ab8
TestMailflowResult : *FAILURE*
MessageLatencyTime : 00:00:00
IsRemoteTest : False
Identity :
IsValid : True

I tried adding -Verbose and -Debug switches and did not get anything useful. I checked to make sure all system mailboxes (Get-Mailbox -Arbitration) were in place and verified the test messages were going out via the transport logs. I dug a little more into how the cmdlet actually works and found that it sends an email with a delivery receipt which led me to look into that. I eventually found that we had our ‘DSNConversionMode‘ set to ‘DoNotConvert’ in our transport configuration:

[PS] C:\Windows\system32>Get-TransportConfig | fl DSNConversionMode
DSNConversionMode : DoNotConvert

After changing it back to the default (UseExchangeDSNs) the cmdlet started working. During testing I was sending email from my mailbox to a system mailbox with the ‘Request a Delivery Receipt‘ option checked. Exchange is expecting the default format in the delivery receipt DSN email and when it is modified Exchange cannot process it.

Delivery receipt with DSNConversionMode set to DoNotConvert:

Delivery receipt with DSNConversionMode set to UseExchangeDSNs:

Citrix Receiver Per-User Install Cleanup

For years Citrix has created the Receiver installer with per-user installation functionality where if the installer is launched in the context of a regular user it will install/register the components to the local user’s profile rather than just failing with a permission error. This creates a huge headache when trying to mass deploy Receiver (now Citrix Workspace) to the environment. You wind up with machines that have both installed. When this happens the user that had the per-user installation cannot launch applications. Even worse the machine/profile usually winds up being in a state where the per-user installation cannot be removed. Even if you get it removed the uninstaller and Citrix’s own cleanup utilities do an awful job at cleaning up the registered classes/components in the per-user installation. Their tools only clean up a fraction of what is actually there. My last two work environments (and current) have been plagued with these installations. I spent time a while back figuring out how to clean it up manually, but it is a major headache to do so. I tried logging a case (and an enhancement request) with Citrix about two years ago stating their Receiver Clean-up Utility utility does not properly clean up these installations. They later came back saying they no longer are supporting the utility. It seems that since then they’ve updated the utility to clean installs up to version 4.3.

Let’s take a look what Citrix is missing in their utility… To do this I take a clean profile, install Citrix Receiver 4.3.100 (not elevated/per-user install), and uninstall it using the Receiver Clean-up Utility (running as an administrator/elevated) while the regular user is still logged in and has their profile loaded. Here is a high-level list of what was left behind in the registry:

  • HKCU\Software\Classes\* – File Associations and COM object registrations
  • HKCU\Software\Classes\AppID\* – AppID registrations
  • HKCU\Software\Classes\Applications\* – More app registrations
  • HKCU\Software\Classes\* – COM object registrations
  • HKCU\Software\Classes\CLSID\* – MANY COM class object GUIDs
  • HKCU\Software\Classes\WOW6432Node\CLSID\* – MANY COM class object GUIDs (32-bit)
  • HKCU\Software\Classes\Interface\* – MANY interface name to interface ID mappings
  • HKCU\Software\Classes\WOW6432Node\Interface\* – MANY interface name to interface ID mappings (32-bit)
  • HKCU\Software\Classes\MIME\Database\Content Type\* – x-ica MIME types
  • HKCU\Software\Classes\PROTOCOLS\Filter\* – Protocol filter handlers
  • HKCU\Software\Classes\Record\*
  • HKCU\Software\Classes\TypeLib\*
  • HKCU\SOFTWARE\MozillaPlugins\* – Firefox plugin registrations
  • HKCU\Software\Microsoft\Installer\Products – MSI installer product codes

In addition to this there are other issues:

  • When it is run against a machine it doesn’t properly load other existing (unloaded) profiles. This caused it not to fully process other user profiles on the machine
  • It doesn’t always kill processes correctly leaving file/directories behind

I decided to build a wrapper script around the Citrix Receiver Clean-up Utility to fill in the gaps. To do so I had to create a full list of everything I had to target. I decided to extract the MSIs from the installer I was testing with and dissect them. I used SuperOrca to pull the ‘Registry’ table from each MSI. I imported those into Excel and used filtering/VLOOKUPs to extract what I needed.

After chopping up the data I am left with the following groups of items to target:

  • A static list of unique registry keys under the user’s profile (this is a good start, but I noticed that some of the IDs in CLSID and Interface are different between versions)
  • A list of values to search for under ‘HKCU\Software\Classes\CLSID’ in order to determine of the root key should be deleted. Also need to target the WOW6432Node path
  • A list of values to search for under ‘HKCU\Software\Classes\Interface’ in order to determine of the root key should be deleted. Also need to target the WOW6432Node path
  • A list of values to search for under ‘HKCU\Software\Microsoft\Installer\Products’ in order to determine of the root key should be deleted. The clean-up utility cleaned up most of this, but one was left over for me

Now that I have the targets it’s time to write the script. In addition to targeting the various registry locations I want to:

  • Identify and load all profile registry hives. This will allow me to run my clean-up process against all profiles, but it will also allow the clean-up utility to process them without the having to be logged in
  • Kill processes that reside in certain paths using wildcards
  • Execute the Citrix Receiver Clean-up Utility silently
  • Clean up a static list of registry keys in all user profiles
  • Search for a list of value strings under in the ‘CLSID’ keys and delete the parent key if a match is found
  • Search for a list of value strings under in the ‘Interface’ keys and delete the parent key if a match is found
  • Search for a list of ‘ProductName‘ value strings under in the ‘Installer\Products’ keys and delete the product key if a match is found
  • Unload all registry hives that were manually loaded in the first step
  • I also wanted the script to work with older versions of PowerShell. I did my best to make it compatible with PS V2

I have tested the script with multiple versions and so far it is working well. It does require that you download the Receiver Clean-up Utility and place the executable in the same directory as the script. Feel free to submit any issues here or in the GitHub repository.

GitHub link: https://github.com/markdepalma/CleanPerUserReceiverInstall

AirWatch API – The argument cannot be null

I recently was creating a PowerShell script that uses the AirWatch REST API to perform mass updates to enrollment users. When testing the process using an API tool (Insomnia) I was receiving the following error when issuing a POST to “/api/V1/system/users/{id}/update“:

<?xml version="1.0" encoding="utf-8"?>
<AirWatchFaultContract
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.air-watch.com/">
  <ErrorCode>1018</ErrorCode>
  <Message>The argument cannot be null</Message>
  <ActivityId>99311627-d7fd-4fa3-bede-78553fe0ac88</ActivityId>
</AirWatchFaultContract>

I was using an XML body to pass one parameter as per the documentation and the user id was correct. I was unable to find any information on this error and the only thing I was left with was using a JSON body instead of XML for the POST. Once I switched to a JSON body the call was successful. I tested other POST commands using an XML body and they did not produce this error.