Leonid Malyshev
Leonid Malyshev

Reputation: 475

Cannot kill process: "No process is associated with this object" error

In my program I try to start a new process (open video file in a default player). This part works OK. Later when I try to close the process (player) I get an error:

System.InvalidOperationException: No process is associated with this object.

My code:

string filename = "747225775.mp4";
var myProc = new Process()
{
    StartInfo = new ProcessStartInfo(filename)
};
myProc.Start();
Thread.Sleep(5000);
try
{
    myProc.Kill(); //Error is here
}
catch (Exception ex)
{
    Debug.WriteLine(ex);
    Debugger.Break();
}

What is wrong?

Upvotes: 5

Views: 20202

Answers (2)

SmallSoft
SmallSoft

Reputation: 728

Process.Start associates the Process object with native process handle only when it spawns new process directly. When filename is used as an argument instead of executable name, Process searches registry for association settings via shell32.dll functions and the exact behavior depends on them.

When association is configured in traditional way, to call command line and transfer file name as 1st argument (such as for Notepad), Process.Start spawns new process directly and correctly associates object with native handle. However, when association is configured to execute COM-object (such as for Windows Media Player), Process.Start only creates some RPC query to execute COM object method and returns without associating object with process handle. (The actual process spawn occurs in svchost.exe context, according to my tests)

This issue can be solved by following modified process start method:

using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;

namespace ProcessTest
{
    public partial class Form1 : Form
    {
        [DllImport("Shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        static extern uint AssocQueryString(AssocF flags, AssocStr str, string pszAssoc, string pszExtra, [Out] StringBuilder pszOut, ref uint pcchOut);

        /*Modified Process.Start*/
        public static Process TrueProcessStart(string filename)
        {
            ProcessStartInfo psi;
            string ext = System.IO.Path.GetExtension(filename);//get extension

            var sb = new StringBuilder(500);//buffer for exe file path
            uint size = 500;//buffer size

            /*Get associated app*/
            uint res = AssocQueryString(AssocF.None, AssocStr.Executable, ext,null, sb, ref size);

            if (res != 0)
            {
                Debug.WriteLine("AssocQueryString returned error: " + res.ToString("X"));
                psi = new ProcessStartInfo(filename);//can't get app, use standard method
            }
            else
            {
                psi = new ProcessStartInfo(sb.ToString(), filename);
            }

            return Process.Start(psi);//actually start process
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {            
            string filename = "c:\\images\\clip.wmv";

            var myProc = TrueProcessStart(filename);
            if (myProc == null)
            {
                MessageBox.Show("Process can't be killed");
                return;
            }

            Thread.Sleep(5000);
            try
            {
                myProc.Kill(); 
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
    }

    [Flags]
    enum AssocF : uint
    {
        None = 0,
        Init_NoRemapCLSID = 0x1,
        Init_ByExeName = 0x2,
        Open_ByExeName = 0x2,
        Init_DefaultToStar = 0x4,
        Init_DefaultToFolder = 0x8,
        NoUserSettings = 0x10,
        NoTruncate = 0x20,
        Verify = 0x40,
        RemapRunDll = 0x80,
        NoFixUps = 0x100,
        IgnoreBaseClass = 0x200,
        Init_IgnoreUnknown = 0x400,
        Init_FixedProgId = 0x800,
        IsProtocol = 0x1000,
        InitForFile = 0x2000,
    }

    enum AssocStr
    {
        Command = 1,
        Executable,
        FriendlyDocName,
        FriendlyAppName,
        NoOpen,
        ShellNewValue,
        DDECommand,
        DDEIfExec,
        DDEApplication,
        DDETopic,
        InfoTip,
        QuickTip,
        TileInfo,
        ContentType,
        DefaultIcon,
        ShellExtension,
        DropTarget,
        DelegateExecute,
        SupportedUriProtocols,
        Max,
    }


}

Here we get the file type's associated application via AssocQueryString. The returned value is then passed to ProcessStartInfo. However it does not always work, so we sometimes have to resort to standart method. For example, image files does not have any associated exe, it's just dll being loaded into explorer's process. So we can't outright kill process in this case.

Upvotes: 2

Brett Caswell
Brett Caswell

Reputation: 1504

to answer your question: "What is wrong?"

I can say the underline cause of this is related to Windows Apps that are launched to handle the type of file (.mp4).


From what I can determine.. there isn't anything wrong with your code sample except that it doesn't account for this scenario (in which, admittingly, I do not understand why it behaves this way).


To replicate this, I used your code sample and a image file (.png). the program launches with 'Photos' by default.

I changed .png files to launch with Paint application by default, then ran the program again. The code sample you've provided worked fine on the desktop application.

Upvotes: 0

Related Questions