我正在尝试使用C#构建一个小型应用程序,该应用程序应该启动/停止IIS Express工作进程。为此,我要使用MSDN上记录的官方“IIS Express API”:http://msdn.microsoft.com/en-us/library/gg418415.aspx

据我了解,该API(仅)基于COM接口(interface)。要使用此COM接口(interface),我通过添加引用-> COM->“IIS安装的版本管理器接口(interface)”在VS2010中添加了对COM库的引用:

到目前为止,一切都很好,但是接下来呢?有一个IIISExprProcessUtility接口(interface),其中包括用于启动/停止IIS进程的两个“方法”。我是否必须编写实现此接口(interface)的类?

public class test : IISVersionManagerLibrary.IIISExprProcessUtility
{
    public string ConstructCommandLine(string bstrSite, string bstrApplication, string bstrApplicationPool, string bstrConfigPath)
    {
        throw new NotImplementedException();
    }

    public uint GetRunningProcessForSite(string bstrSite, string bstrApplication, string bstrApplicationPool, string bstrConfigPath)
    {
        throw new NotImplementedException();
    }

    public void StopProcess(uint dwPid)
    {
        throw new NotImplementedException();
    }
}

如您所见,我不是专业开发人员。有人可以指出我正确的方向。
任何帮助是极大的赞赏。

更新1:
根据建议,我尝试了以下代码,但不幸的是,该代码不起作用:

好的,可以实例化它,但是我看不到如何使用该对象...


IISVersionManagerLibrary.IIISExpressProcessUtility test3 = (IISVersionManagerLibrary.IIISExpressProcessUtility) Activator.CreateInstance(Type.GetTypeFromCLSID(new Guid("5A081F08-E4FA-45CC-A8EA-5C8A7B51727C")));

Exception: Retrieving the COM class factory for component with CLSID {5A081F08-E4FA-45CC-A8EA-5C8A7B51727C} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).

最佳答案

我正在尝试做类似的事情。我得出的结论是Microsoft提供的COM库不完整。我之所以不使用它,是因为该文档提到“注意:本主题是预发行文档,并且在以后的发行中可能会发生变化”。

因此,我决定看看IISExpressTray.exe在做什么。它似乎在做类似的事情。

我反汇编了IISExpressTray.dll,发现列出所有IISexpress进程并停止IISexpress进程并没有什么魔力。

它不会调用该COM库。它不会从注册表中查找任何内容。

因此,我得出的解决方案非常简单。要启动IIS Express进程,我只使用Process.Start()并传入我需要的所有参数。

为了停止IIS Express进程,我使用了反射器从IISExpressTray.dll复制了代码。我看到它只是向目标IISExpress进程发送WM_QUIT消息。

这是我编写的用于启动和停止IIS Express进程的类。希望这可以帮助其他人。

class IISExpress
{
    internal class NativeMethods
    {
        // Methods
        [DllImport("user32.dll", SetLastError = true)]
        internal static extern IntPtr GetTopWindow(IntPtr hWnd);
        [DllImport("user32.dll", SetLastError = true)]
        internal static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
        [DllImport("user32.dll", SetLastError = true)]
        internal static extern uint GetWindowThreadProcessId(IntPtr hwnd, out uint lpdwProcessId);
        [DllImport("user32.dll", SetLastError = true)]
        internal static extern bool PostMessage(HandleRef hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
    }

    public static void SendStopMessageToProcess(int PID)
    {
        try
        {
            for (IntPtr ptr = NativeMethods.GetTopWindow(IntPtr.Zero); ptr != IntPtr.Zero; ptr = NativeMethods.GetWindow(ptr, 2))
            {
                uint num;
                NativeMethods.GetWindowThreadProcessId(ptr, out num);
                if (PID == num)
                {
                    HandleRef hWnd = new HandleRef(null, ptr);
                    NativeMethods.PostMessage(hWnd, 0x12, IntPtr.Zero, IntPtr.Zero);
                    return;
                }
            }
        }
        catch (ArgumentException)
        {
        }
    }

    const string IIS_EXPRESS = @"C:\Program Files\IIS Express\iisexpress.exe";
    const string CONFIG = "config";
    const string SITE = "site";
    const string APP_POOL = "apppool";

    Process process;

    IISExpress(string config, string site, string apppool)
    {
        Config = config;
        Site = site;
        AppPool = apppool;

        StringBuilder arguments = new StringBuilder();
        if (!string.IsNullOrEmpty(Config))
            arguments.AppendFormat("/{0}:{1} ", CONFIG, Config);

        if (!string.IsNullOrEmpty(Site))
            arguments.AppendFormat("/{0}:{1} ", SITE, Site);

        if (!string.IsNullOrEmpty(AppPool))
            arguments.AppendFormat("/{0}:{1} ", APP_POOL, AppPool);

        process = Process.Start(new ProcessStartInfo()
        {
            FileName = IIS_EXPRESS,
            Arguments = arguments.ToString(),
            RedirectStandardOutput = true,
            UseShellExecute = false
        });
    }

    public string Config { get; protected set; }
    public string Site { get; protected set; }
    public string AppPool { get; protected set; }

    public static IISExpress Start(string config, string site, string apppool)
    {
        return new IISExpress(config, site, apppool);
    }

    public void Stop()
    {
        SendStopMessageToProcess(process.Id);
        process.Close();
    }
}

我不需要列出所有现有的IIS express过程。如果需要的话,根据我在反射器中看到的内容,IISExpressTray.dll的作用是调用Process.GetProcessByName("iisexpress", ".")
要使用我提供的类,这是我用来测试的示例程序。
class Program
{

    static void Main(string[] args)
    {
        Console.Out.WriteLine("Launching IIS Express...");
        IISExpress iis1 = IISExpress.Start(
            @"C:\Users\Administrator\Documents\IISExpress\config\applicationhost.config",
            @"WebSite1(1)",
            @"Clr4IntegratedAppPool");

        IISExpress iis2 = IISExpress.Start(
            @"C:\Users\Administrator\Documents\IISExpress\config\applicationhost2.config",
            @"WebSite1(1)",
            @"Clr4IntegratedAppPool");

        Console.Out.WriteLine("Press ENTER to kill");
        Console.In.ReadLine();

        iis1.Stop();
        iis2.Stop();
    }
}

这可能不是您问题的答案,但我认为对您的问题感兴趣的人可能会发现我的工作很有用。随时改进代码。您可能需要增强一些地方。
  • 无需对iisexpress.exe位置进行硬编码,您可以修复我的代码以从注册表中读取。
  • 我没有包括iisexpress.exe支持的所有参数
  • 我没有执行错误处理。因此,如果IISExpress进程由于某种原因而无法启动(例如,使用了端口),我不知道。我认为最简单的解决方法是监视StandardError流,如果我从StandardError流
  • 中得到任何东西,则抛出异常

    关于c# - 以编程方式启动和停止IIS Express,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4772092/

    10-09 06:54