Easily track Windows 10 Intune App deployments from the Endpoint – Support Help #2

2
Easily track Windows 10 Intune App deployments from the Endpoint - Support Help #2

Hi and welcome to today’s post titled “Easily track Windows 10 Intune App deployments from the Endpoint – Support Help #2

This is a continuation from my previous post Easily track Windows 10 Intune MDM policies – Support Help #1 where I have tried to explain how you can use Windows registry and events to help troubleshoot issues related to Windows 10 Intune MDM policy deployment issues.

Today we will continue on the same journey, exploring how we can troubleshoot Intune app deployment issues using the Windows 10 registry and events.

Let’s get started.

Types of Intune supported app deployment for Windows 10 platform

Intune supports a variety of app types and deployment scenarios for the Windows 10 platform as highlighted below.

  • Weblink for internal web apps
  • MSfB Online/Offline apps [Store Apps]
  • M365 Apps (O365 Pro Plus package)
  • Microsoft Edge
  • LOB app  (.msi, .appx, .appxbundle, .msix, and .msixbundle)
  • Win32 (.exe wrapped as .intunewin)
Windows 10 Intune App Deployment Support Help #2 - Intune supporrted app types for deployments on Windows 10 endpoints
Windows 10 Intune App Deployment Support Help #2 – Intune supporrted app types for deployments on Windows 10 endpoints

However, all would agree to the fact that on a day to day basis for Windows 10 platform, as an Intune IT Pro, we mostly have to deal with issues related to LOB and Win32 app deployments.

Since Win32 app deployment troubleshooting is already covered previously on my blog titled Intune Management Extension Level 3 Troubleshooting Guide Intune win32 App, as such, I thought of keeping the focus of this article on the support of Windows 10 LOB app deployment from Intune.

Understanding Intune Windows 10 App Deployment High-level flow…

I always believe that for effective troubleshooting, an engineer should have a grasp on the overall flow to understand what are the breakpoints involved and accordingly determine the cause for the fix.

So first, let us understand the highlevel flow of Windows 10 app deployment from Intune.

Consider an application is created in Intune for Windows 10. Irrespective of the type of app being created, Store app/LOB app/Weblink, Intune will create an Application object identifiable via a GUID.

Windows 10 Intune App Deployment Support Help #2 - Irrespective of the type of app being created, Store app/LOB app/Weblink, Intune will create an Application object identifiable via a GUID.
Windows 10 Intune App Deployment Support Help #2 – Irrespective of the type of app being created, Store app/LOB app/Weblink, Intune will create an Application object identifiable via a GUID.

The Application Object is stored to the Azure Blob Storage which every Intune tenant comes with for storing all policy configuration settings and serves the Intune CDN for delivery and deployments.

If the app object is a Microsoft Store App, the object content is a deep-link to the respective Store app, and deployment of the app is handled by the Store services.

For a Microsoft Store for Business app,

  • If the app type is Offline and is free of charge, the deployment is handled by Intune.
  • If the app type is Online, the deployment is handled by the Store services.

For more info on the above, check here.

If it is a LOB app, the object content will contain the app package as uploaded during the app creation. Intune will handle the app deployment and the app will be served from the Intune CDN.

Now an app can be deployed either as an Available or Required.

Depending on the deployment type, below flow of actions would be an overview of the process that will happen.

Application deployed as Available

  • User opens the Company Portal app on the endpoint (or can be accessed via web https://portal.manage.microsoft.com/)
  • User searches for the app
  • The user initiates the app installation by clicking on the Install button triggering the DownloadInstall action.
Easily track Windows 10 Intune App deployments from the Endpoint - Support Help #2 1
Windows 10 Intune App Deployment Support Help #2 – User triggers the Install action for an app deployed as Available. For apps deployed as Required, Intune enforces the install action.

Application deployed as Required

  • Intune will initiate a Push Notification to invoke the DM Client of the endpoint.
  • Push Notification Provider (WNS) will notify the DM client on the target device to initiate a connection to service.
  • DM client then initiates a connection to the management server. An OMA-DM session starts.
  • Intune sends the app instruction with intent DownloadInstall or StoreInstall [Trigger the application installation depending on whether the app is a LOB or a Store app]

The DM client knows if the app install instruction as sent is for a Store App or LOB app by reading the LocURI element of the SyncML instruction.

This is how the SyncML instruction from Intune looks like which is received by the endpoint.

<Add>
       <CmdID>xx</CmdID>
              <Item>
                     <Target>
                             <LocURI>./User/Vendor/MSFT/EnterpriseModernAppManagement/AppInstallation/Microsoft.Office.Sway_8wekyb3d8bbwe</LocURI>
                         </Target>
             </Item>
 </Add>
 <Exec>
         <CmdID>xx</CmdID>
                 <Item>
                         <Target>
                              <LocURI>./User/Vendor/MSFT/EnterpriseModernAppManagement/AppInstallation/Microsoft.Office.Sway_8wekyb3d8bbwe/StoreInstall</LocURI>
                         </Target>
                    <Meta>
                              <A:Format>xml</A:Format>
                              <A:Type>text/plain</A:Type>
                         </Meta>
              <Data>&lt;Application id="9WZDNCRD2G0J" flags="1" skuid="0016" /&gt;</Data>
         </Item>
  </Exec>

As an overview, the request is redirected to the respective store via the deep link and the Store handles the rest of the delivery mechanism and installation.

This is how the SyncML instruction from Intune looks like which is received by the endpoint.

<Atomic>
      <CmdID>xx</CmdID>
              <Add>
                    <CmdID>xx</CmdID>
                         <Item>
                              <Target>
                                   <LocURI>./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7BD3BC954F-D661-474C-B367-30EB6E56542E%7D/DownloadInstall</LocURI>
                              </Target>
                         </Item>
                </Add>
                 <Exec>
                      <CmdID>xx</CmdID>
                         <Item>
                              <Target>
                                   <LocURI>./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7BD3BC954F-D661-474C-B367-30EB6E56542E%7D/DownloadInstall</LocURI>
                              </Target>
                              <Meta>
                                   <A:Format>xml</A:Format>
                                   <A:Type>text/plain</A:Type>
                              </Meta>
                              <Data>&lt;MsiInstallJob id="{D3BC954F-D661-474C-B367-30EB6E56542E}"&gt;&lt;Product Version="2.1.8.105"&gt;&lt;Download&gt;&lt;ContentURLList&gt;&lt;ContentURL&gt;https://fef.msuc02.manage.microsoft.com/ContentService/DownloadService/GetAppActive/WinRT?contentGuid=8edd097e-6f04-4919-a211-2ed5476240bd&amp;amp;fileNameHash=e35b30c2-e68a-4cd8-aa5d-7ef8bb798cbc.msi.bin&amp;amp;api-version=1.0&lt;/ContentURL&gt;&lt;/ContentURLList&gt;&lt;/Download&gt;&lt;Validation&gt;&lt;FileHash&gt;C73D373275519DE5545824FF20E886E4C2D76770CB77F8B685C0B52A1C07E97D&lt;/FileHash&gt;&lt;/Validation&gt;&lt;Enforcement&gt;&lt;CommandLine&gt;/qn&lt;/CommandLine&gt;&lt;RetryCount&gt;5&lt;/RetryCount&gt;&lt;RetryInterval&gt;3&lt;/RetryInterval&gt;&lt;/Enforcement&gt;&lt;/Product&gt;&lt;/MsiInstallJob&gt;</Data>
                         </Item>
                    </Exec>
               </Atomic>

As an overview, there is a BITS download job created to get the package downloaded from the Intune CDN post which there is an Exec operation during which the app is subjected to installation.

The difference in how the app deployments are handled on the endpoint based on the app type can be further understood by the difference in the Exec command that Intune sends for the two different app types.

  • For an MSI LOB app, the EXEC instruction is DownloadInstall
  • For a Store app, the EXEC instruction is StoreInstall

Windows 10 Intune App Deployment Issues – LOB (MSI) Application

As stated above already, MSI App deployment from Intune is taken care of by the EnterpriseDesktopAppManagement CSP on the endpoint which the DM Client will invoke when it receives an instruction from Intune to install a LOB app.

Tracking Intune Windows 10 LOB app deployment via Windows Events

You can track LOB app deployments (for both Available or Required) using Windows events as shown below.

Event 1901, DeviceManagement-Enterprise-Diagnostics-Provider

EnterpriseDesktopAppManagement CSP: A node instance of was created successfully. MSI ProductCode: {D3BC954F-D661-474C-B367-30EB6E56542E}, MSI UpgradeCode: null, User SID: (S-0-0-00-0000000000-0000000000-000000000-000).
Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app deployment using Windows Events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app deployment using Windows Events

Note: MSI app deployment on the endpoint is tracked against the MSI product code and not the App GUID as seen in Intune.

Windows 10 Intune App Deployment Support Help #2 - MSI app records on the endpoint (Windows Event and Registry entry) are created based on the MSI product code and not the app GUID as in Intune.
Windows 10 Intune App Deployment Support Help #2 – MSI app records on the endpoint (Windows Event and Registry entry) are created based on the MSI product code and not the app GUID as in Intune.
Event 1904, DeviceManagement-Enterprise-Diagnostics-Provider

EnterpriseDesktopAppManagement CSP: MDMAppInstaller task has started.
Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app deployment using Windows Events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app deployment using Windows Events

An LOB (MSI) app deployment is a two phase process on the endpoint –

  • Download of the app package to the local storage on the endpoint
  • Execution of the app package for the actual install

As such, once the app instance node is created, you would see a corresponding BITS job being created to get the MSI package downloaded from Intune CDN to the endpoint.

Event 1905, DeviceManagement-Enterprise-Diagnostics-Provider

EnterpriseDesktopAppManagement CSP: Application content download started. MSI ProductCode: {D3BC954F-D661-474C-B367-30EB6E56542E}, User SID: (S-0-0-00-0000000000-0000000000-000000000-000), BITS job: (9274a627-e068-4323-a9f1-528080e7ba72).
Easily track Windows 10 Intune App deployments from the Endpoint - Support Help #2 2
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app deployment using Windows Events

You will get information on the corresponding BITS jobs from the BITS-Client events which can help you to trace any errors faced during the download phase.

Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app download using BITS-Client events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app download using BITS-Client events
Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app download using BITS-Client events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app download using BITS-Client events
Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app download using BITS-Client events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app download using BITS-Client events
Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app download using BITS-Client events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app download using BITS-Client events

If the download phase has faced no errors and the BITS job is completed successfully as above, you get the corresponding DM-Ent-Diag-Prov event as below

Event 1906, DeviceManagement-Enterprise-Diagnostics-Provider

EnterpriseDesktopAppManagement CSP: Application content download completed. MSI ProductCode: {D3BC954F-D661-474C-B367-30EB6E56542E}, User SID: (S-0-0-00-0000000000-0000000000-000000000-000), BITS job: (9274a627-e068-4323-a9f1-528080e7ba72).
Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app deployment using Windows Events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app deployment using Windows Events

However, if there are any errors in the download phase itself, the BITS-Client events for the download job would help you to understand the issue.

Once the package download is complete, the next phase starts which is the Execution of the app package for the installation.

Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app deployment using Windows Events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app deployment using Windows Events

To which path is the MSI app package downloaded to the local storage on the endpoint?

The MSI app package is downloaded to the local storage path C:\Windows\system32\config\systemprofile\AppData\Local\mdm

The above path is a temporary cache location.

Once the install is successful, the downloaded app package file is purged. If only the install fails, you will find the downloaded app package file here with the MSI product code as the file name.

How do we know that this is the location to which the app package is downloaded?

Well, the answer is there in the MsiInstaller events [Application Events].

Event 1040, MsiInstaller [Application Events]

Beginning a Windows Installer transaction: C:\Windows\system32\config\systemprofile\AppData\Local\mdm\{D3BC954F-D661-474C-B367-30EB6E56542E}.msi. Client Process Id: 5596.

Note the location from where the app install is being triggered!

If the install is successful, you would get a Success event as below.

Event 11707, MsiInstaller [Application Events]

Product: Microsoft Garage Mouse without Borders - - Installation completed succesfully.

And the end of the process.

Event 11707, MsiInstaller [Application Events]

Ending a Windows Installer transaction: C:\Windows\system32\config\systemprofile\AppData\Local\mdm\{D3BC954F-D661-474C-B367-30EB6E56542E}.msi. Client Process Id: 5596.

Else you would be seeing an Error event for the MsiInstaller process, using which you can further diagnose why the app package failed the install.

One of the most common issues for MSI app install failure is either issue with the command line provided to trigger the silent install or the package itself does not supports silent install as it requires user input to continue with the setup.

MSI app package must be able to install silently in order for Intune to be able to successfully deploy it on the endpoints.

For success, you would get the corresposnidng event in DM-Ent-Diag-Prov Events

Event 1922, DeviceManagement-Enterprise-Diagnostics-Provider

EnterpriseDesktopAppManagement CSP: An application install has succeeded. MSI ProductCode: {D3BC954F-D661-474C-B367-30EB6E56542E}, User SID: (S-0-0-00-0000000000-0000000000-000000000-000), Result: (The operation completed successfully.).
Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app deployment using Windows Events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app deployment using Windows Events

Whether the Execution exit status is a Success or an Error, there is a Status Alert sent to Intune to update the management service regarding the final deployment status for the current iteration.

Intune as a management service queries the endpoint on the status of the current transaction for the app deployment.

 <Get>
      <CmdID>xx</CmdID>
      <Item>
        <Target>
          <LocURI>./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7BD3BC954F-D661-474C-B367-30EB6E56542E%7D/Status</LocURI>
        </Target>
      </Item>
    </Get>
    <Get>
      <CmdID>xx</CmdID>
      <Item>
        <Target>
          <LocURI>./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7BD3BC954F-D661-474C-B367-30EB6E56542E%7D/LastError</LocURI>
        </Target>
      </Item>
    </Get>
    <Get>
      <CmdID>xx</CmdID>
      <Item>
        <Target>
          <LocURI>./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7BD3BC954F-D661-474C-B367-30EB6E56542E%7D/LastErrorDesc</LocURI>
        </Target>
      </Item>
    </Get>

And this is how the DM Client responds back.

 <Results>
      <CmdID>xx</CmdID>
      <MsgRef>xx</MsgRef>
      <CmdRef>xx</CmdRef>
      <Item>
        <Source>
          <LocURI>./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7BD3BC954F-D661-474C-B367-30EB6E56542E%7D/Status</LocURI>
        </Source>
        <Meta>
          <Format xmlns="syncml:metinf">int</Format>
        </Meta>
        <Data>70</Data>
      </Item>
    </Results>
<Results>
      <CmdID>xx</CmdID>
      <MsgRef>xx</MsgRef>
      <CmdRef>xx</CmdRef>
      <Item>
        <Source>
          <LocURI>./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7BD3BC954F-D661-474C-B367-30EB6E56542E%7D/LastError</LocURI>
        </Source>
        <Meta>
          <Format xmlns="syncml:metinf">int</Format>
        </Meta>
        <Data>0</Data>
      </Item>
    </Results>
<Results>
      <CmdID>20</CmdID>
      <MsgRef>5</MsgRef>
      <CmdRef>11</CmdRef>
      <Item>
        <Source>
          <LocURI>./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/%7BD3BC954F-D661-474C-B367-30EB6E56542E%7D/LastErrorDesc</LocURI>
        </Source>
        <Data>The operation completed successfully.</Data>
      </Item>
    </Results>

SyncML messages are thanks to SyncML Viewer by Oliver Kieselbach.

The corresponding events in the DM-Ent-Diag-Prov

Event 1927, DeviceManagement-Enterprise-Diagnostics-Provider

EnterpriseDesktopAppManagement CSP: An application status alert was sent to the device management service. LocURI: (./Device/Vendor/MSFT/EnterpriseDesktopAppManagement/MSI/{D3BC954F-D661-474C-B367-30EB6E56542E}/DownloadInstall), Alert Data: (0x0).
Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app deployment using Windows Events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app deployment using Windows Events
Event 1912, DeviceManagement-Enterprise-Diagnostics-Provider

EnterpriseDesktopAppManagement CSP: The MDMAppInstaller process is terminating with no errors.
Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app deployment using Windows Events
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app deployment using Windows Events

Tracking Intune Windows 10 LOB app deployment via Windows Registry

The app instance node creation as stated in DM-Ent-Diag Provider Event ID 1901 is actually creating the app entry in the registry. All the information as was provided above can also be easily tracked using the registry for tracing deployment issues.

LOB app deployment details can be checked from the following registry path HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\EnterpriseDesktopAppManagement

There will be two sub keys corresponding to the

  • system SID (all zeros) [will list all device context MSI deployments]
  • user SID [will list all user context MSI deployments]

Under those subkeys, you will find the MSI app deployments from Intune listed using the MSI Product ID of the package.

Windows 10 Intune App Deployment Support Help #2 - Tracking MSI app deployment using Windows Registry
Windows 10 Intune App Deployment Support Help #2 – Tracking MSI app deployment using Windows Registry

The important keys are within an app entry are below.

  • AssignmentType signifies the deployment, whether the assignment is Required or Available
  • BITSJobId points to the download job created to download the app package
  • CurrentDownloadUrl points to the Intune CDN from where the package will be downloaded
  • CommandLine shows the install command defined while creating the app package in Intune
  • Status shows the enforcement status, whether Success or Failed.

Below table shows the possible values that you may encounter for Status

MeaningValue
Initialized10
Download In Progress20
Pending Download Retry25
Download Failed30
Download Completed40
Pending User Session48
Enforcement In Progress50
Pending Enforcement Retry55
Enforcement Failed60
Enforcement Completed70
Table 1: Possible values for Status

The registry will also give you some more important information in case you are actually working with a failure scenario.

  • EnforcementRetryCount signifies the number of time the enforcement will be retried or re-attempted
  • EnforcementRetryIndex signifies the current retry value
  • EnforcementRetryInterval signifies the time in which the successive retry will be attempted (in minutes)
  • EnforcementTimeout is the time till which it will wait for the installer process to complete and report status (30 mins default)
  • LastError shows the Status of the last retry attempt

If the install fails post successful download of the LOB app package, the install execution is attempted thrice for the current enforcement before Global Re-evaluation Scheme (GRS) will kick in and block any further retry attempt for the next 24 hours. [Applicable for Required assignment]

To manually re-trigger the enforcement again for a LOB deployed with Required intent, you need to

  • clear the values for LastError and Status
  • reset values of EnforcementRetryCount and EnforcementRetryIndex to 0

Need further help in troubleshooting MSI app deployment. Read this excellent blog available on the Microsoft Tech Community blogs.

Windows 10 Intune App Deployment Issues – Store Application

As stated earlier, Store App deployment from Intune is taken care of by the EnterpriseModernAppManagement CSP on the endpoint which the DM Client will invoke when it receives an instruction from Intune to install a Store app.

Intune as a management service only invokes the DM Client of the endpoint to start the transaction. However, it is just a deep-link to the Store. The delivery and installation are taken care of by the Store services and the OS platform.

When it comes to tracking Store app deployments, I was only able to get to see the apps being deployed from Intune here at reg_path HKLM\Software\Microsoft\EnterpriseResourceManager\Tracked\{Enrollment GUID}\

Windows 10 Intune App Deployment Support Help #2 - Tracking Store App deployment using Windows Registry
Windows 10 Intune App Deployment Support Help #2 – Tracking Store App deployment using Windows Registry

I was also able to view deployment-related events from under

Application and Services Logs > Microsoft > Windows > AppXDeployment-Server/Operational

Windows 10 Intune App Deployment Support Help #2 - Tracking Store App deployment using Windows Events
Windows 10 Intune App Deployment Support Help #2 – Tracking Store App deployment using Windows Events

Application and Services Logs > Microsoft > Windows > Store/Operational

Windows 10 Intune App Deployment Support Help #2 - Tracking Store App deployment using Windows Events
Windows 10 Intune App Deployment Support Help #2 – Tracking Store App deployment using Windows Events

Windows 10 Intune App Deployment Issues – Intune Sidecar deployments (Win32 and PS Scripts)

Win32 application deployments from Intune are via the Intune Sidecar a.k.a Intune Management Extension.

The IME agent is itself an MSI app package that gets deployed to the endpoints automatically if Intune evaluates there is a PS script or Win32 app deployment and the endpoint meets the prerequisites of Intune Sidecar.

As such in issues related to the IME agent installation itself, you can check the status as above using information from the registry and events.

Windows 10 Intune App Deployment Support Help #2 - The IME agent is itself an MSI app package that gets deployed to the endpoints automatically if Intune evaluates there is a PS script or Win32 app deployment and the endpoint meets the prerequisites for IME.
Windows 10 Intune App Deployment Support Help #2 – The IME agent is itself an MSI app package that gets deployed to the endpoints automatically if Intune evaluates there is a PS script or Win32 app deployment and the endpoint meets the prerequisites for IME.

Support of PS script (IME agent as such) for Azure AD registered devices (means BYOD yeah!) is a feature in development as I last checked documented here Microsoft post.

PowerShell Scripts information from Registry

  • User Targeted – HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IntuneManagementExtension\Policies\{UserGUID}\{ScriptGUID}
  • Device Targeted – HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IntuneManagementExtension\Policies\{0000}\{ScriptGUID}

You can refer to this blog post from Oliver Kieselbach for further troubleshooting help on PS script deployment issues.

Win32 Apps Information from Registry

  • User Targeted – HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IntuneManagementExtension\Win32Apps\{UserGUID}\{AppGUID}
  • Device Targeted – HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\IntuneManagementExtension\Win32Apps\{0000}\{AppGUID}

You can collect IME logs from location C:\ProgramData\Microsoft\IntuneManagementExtension\Logs

For more detailed troubleshooting help related to Win32 apps, you can refer to my own article here.

In my article on Endpoint Analytics, I had already covered how you can track Health Scripts a.k.a Proactive Remediation script packages since it utilizes the same IME architecture on the endpoint. Give it a read!

If you are yet to use Endpoint Analytics or planning to use it but have doubts, I would recommend giving it a try. Endpoint Analytics is in GA and not in preview anymore!

The End

I hope the information as shared above will help you while dealing with Windows 10 Intune App deployment issues.

Well that was all for today. Continue staying safe!

Additional articles you may want to check:

2 COMMENTS

LEAVE A REPLY

Please enter your comment!
Please enter your name here

This site uses Akismet to reduce spam. Learn how your comment data is processed.