C# 如何从程序中启动Azure Storage Emulator

C# 如何从程序中启动Azure Storage Emulator,c#,azure,azure-storage,C#,Azure,Azure Storage,我有一些使用Azure存储的单元测试。在本地运行这些时,我希望它们使用Azure存储模拟器,它是Azure SDK v1.5的一部分。如果模拟器没有运行,我希望它启动 要从命令行启动emulator,我可以使用以下命令: "C:\Program Files\Windows Azure SDK\v1.5\bin\csrun" /devstore 这个很好用 当我试图用这个C代码启动它时,它崩溃了: using System.IO; using System.Diagnostics; ... Pr

我有一些使用Azure存储的单元测试。在本地运行这些时,我希望它们使用Azure存储模拟器,它是Azure SDK v1.5的一部分。如果模拟器没有运行,我希望它启动

要从命令行启动emulator,我可以使用以下命令:

"C:\Program Files\Windows Azure SDK\v1.5\bin\csrun" /devstore
这个很好用

当我试图用这个C代码启动它时,它崩溃了:

using System.IO;
using System.Diagnostics;
...
ProcessStartInfo processToStart = new ProcessStartInfo() 
{   
    FileName = Path.Combine(SDKDirectory, "csrun"),
    Arguments = "/devstore"
};
Process.Start(processToStart);
我尝试过摆弄一些ProcessStartInfo设置,但似乎没有任何效果。还有其他人有这个问题吗

我检查了应用程序事件日志,发现以下两个条目:

事件ID:1023 .NET运行时版本2.0.50727.5446-致命的执行引擎错误(000007FEF46B40D2)(80131506)

事件ID:1000 故障应用程序名称:DSService.exe,版本:6.0.6002.18312,时间戳:0x4e5d8cf3 故障模块名称:mscorwks.dll,版本:2.0.50727.5446,时间戳:0x4d8cdb54 异常代码:0xc0000005 故障偏移量:0x00000000001de8d4 出错进程id:0x%9 错误应用程序启动时间:0x%10 正在出错的应用程序路径:%11 发生故障的模块路径:%12
报告Id:%13

可能是由于找不到文件造成的

试试这个

FileName = Path.Combine(SDKDirectory, "csrun.exe")

这个项目对我来说效果很好。试一试,如果它对你也有效,那就从那往后退。(你的应用程序与此不同吗?)


我卸载了所有Windows Azure位:

  • WA SDK v1.5.20830.1814
  • 用于Visual Studio的WA工具:v1.5.40909.1602
  • WA AppFabric:v1.5.37
  • WA AppFabric:v2.0.224
然后,我使用统一安装程序下载并安装了所有内容。除了AppFabric v2,所有的东西都回来了。所有版本号都相同。重新运行我的测试,但仍然有问题

然后…(这很奇怪)…它偶尔会起作用。重新启动机器,现在可以工作了。现在已经关闭并重新启动了很多次…而且它可以正常工作。(叹气)

感谢所有提供反馈和/或想法的人

最后的代码是:

    static void StartAzureStorageEmulator()
    {
        ProcessStartInfo processStartInfo = new ProcessStartInfo()
        {
            FileName = Path.Combine(SDKDirectory, "csrun.exe"),
            Arguments = "/devstore",
        };
        using (Process process = Process.Start(processStartInfo))
        {
            process.WaitForExit();
        }
    }

仅供参考-1.6默认位置为C:\Program Files\Windows Azure Emulator\Emulator,如上所述。

我们遇到了相同的问题。我们有一个“冒烟测试”的概念,它在测试组之间运行,确保在下一组开始之前环境处于良好状态。我们有一个启动冒烟测试的.cmd文件,它可以很好地启动devfabric仿真器,但是devstore仿真器只在.cmd进程运行时运行


显然,DSServiceSQL.exe的实现不同于DFService.exe。DFService似乎像windows服务一样运行—启动它,它就会继续运行。DSServiceSQL在启动它的进程一结束就消失。

于2015年1月19日更新:

在做了更多的测试(即运行了几个构建)之后,我发现,
WAStorageEmulator.exe
实际上在几个重要方面被破坏了(这可能会或可能不会影响您如何使用它)

即使现有进程正在运行,如果用户在现有正在运行的进程和用于启动状态进程的用户之间存在差异,状态也会报告
False
。此不正确的状态报告将导致无法启动流程,如下所示:

C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator>WAStorageEmulator.exe status
if(!AzureStorageEmulatorAutomation.IsEmulatorRunning())
{
    AzureStorageEmulatorAutomation emulator = new AzureStorageEmulatorAutomation();
    emulator.Start();

    // Even clear some things
    emulator.ClearBlobs();
    emulator.ClearTables();
    emulator.ClearQueues();

    emulator.Stop();
}
此外,status命令仅用于报告在
WAStorageEmulator.exe.config
中指定的端点,而不是现有正在运行的进程的端点。也就是说,如果启动emulator,然后更改配置文件,然后调用status,它将报告配置中列出的端点

考虑到所有这些警告,事实上,使用原始实现可能会更好,因为它看起来更可靠

我将两者都留下,以便其他人可以选择对他们有效的解决方案

于2015年1月18日更新:

我已经完全重写了这段代码,以便按照@RobertKoritnik的请求正确利用
WAStorageEmulator.exe

public static class AzureStorageEmulatorManager
{
    public static bool IsProcessRunning()
    {
        bool status;

        using (Process process = Process.Start(StorageEmulatorProcessFactory.Create(ProcessCommand.Status)))
        {
            if (process == null)
            {
                throw new InvalidOperationException("Unable to start process.");
            }

            status = GetStatus(process);
            process.WaitForExit();
        }

        return status;
    }

    public static void StartStorageEmulator()
    {
        if (!IsProcessRunning())
        {
            ExecuteProcess(ProcessCommand.Start);
        }
    }

    public static void StopStorageEmulator()
    {
        if (IsProcessRunning())
        {
            ExecuteProcess(ProcessCommand.Stop);
        }
    }

    private static void ExecuteProcess(ProcessCommand command)
    {
        string error;

        using (Process process = Process.Start(StorageEmulatorProcessFactory.Create(command)))
        {
            if (process == null)
            {
                throw new InvalidOperationException("Unable to start process.");
            }

            error = GetError(process);
            process.WaitForExit();
        }

        if (!String.IsNullOrEmpty(error))
        {
            throw new InvalidOperationException(error);
        }
    }

    private static class StorageEmulatorProcessFactory
    {
        public static ProcessStartInfo Create(ProcessCommand command)
        {
            return new ProcessStartInfo
            {
                FileName = @"C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\WAStorageEmulator.exe",
                Arguments = command.ToString().ToLower(),
                RedirectStandardOutput = true,
                RedirectStandardError = true,
                UseShellExecute = false,
                CreateNoWindow = true
            };
        }
    }

    private enum ProcessCommand
    {
        Start,
        Stop,
        Status
    }

    private static bool GetStatus(Process process)
    {
        string output = process.StandardOutput.ReadToEnd();
        string isRunningLine = output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).SingleOrDefault(line => line.StartsWith("IsRunning"));

        if (isRunningLine == null)
        {
            return false;
        }

        return Boolean.Parse(isRunningLine.Split(':').Select(part => part.Trim()).Last());
    }

    private static string GetError(Process process)
    {
        string output = process.StandardError.ReadToEnd();
        return output.Split(':').Select(part => part.Trim()).Last();
    }
}
以及相应的测试:

[TestFixture]
public class When_starting_process
{
    [Test]
    public void Should_return_started_status()
    {
        if (AzureStorageEmulatorManager.IsProcessRunning())
        {
            AzureStorageEmulatorManager.StopStorageEmulator();
            Assert.That(AzureStorageEmulatorManager.IsProcessRunning(), Is.False);
        }

        AzureStorageEmulatorManager.StartStorageEmulator();
        Assert.That(AzureStorageEmulatorManager.IsProcessRunning(), Is.True);
    }
}

[TestFixture]
public class When_stopping_process
{
    [Test]
    public void Should_return_stopped_status()
    {
        if (!AzureStorageEmulatorManager.IsProcessRunning())
        {
            AzureStorageEmulatorManager.StartStorageEmulator();
            Assert.That(AzureStorageEmulatorManager.IsProcessRunning(), Is.True);
        }

        AzureStorageEmulatorManager.StopStorageEmulator();
        Assert.That(AzureStorageEmulatorManager.IsProcessRunning(), Is.False);
    }
}
原创帖子:

我将Doug Cratter和Smarx的代码向前推进了一步,并创建了一个实用程序类:

下面的代码已经更新,可以在Windows 7和8上运行,现在指向SDK 2.4中的新存储仿真程序路径**

public static class AzureStorageEmulatorManager
{
    private const string _windowsAzureStorageEmulatorPath = @"C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\WAStorageEmulator.exe";
    private const string _win7ProcessName = "WAStorageEmulator";
    private const string _win8ProcessName = "WASTOR~1";

    private static readonly ProcessStartInfo startStorageEmulator = new ProcessStartInfo
    {
        FileName = _windowsAzureStorageEmulatorPath,
        Arguments = "start",
    };

    private static readonly ProcessStartInfo stopStorageEmulator = new ProcessStartInfo
    {
        FileName = _windowsAzureStorageEmulatorPath,
        Arguments = "stop",
    };

    private static Process GetProcess()
    {
        return Process.GetProcessesByName(_win7ProcessName).FirstOrDefault() ?? Process.GetProcessesByName(_win8ProcessName).FirstOrDefault();
    }

    public static bool IsProcessStarted()
    {
        return GetProcess() != null;
    }

    public static void StartStorageEmulator()
    {
        if (!IsProcessStarted())
        {
            using (Process process = Process.Start(startStorageEmulator))
            {
                process.WaitForExit();
            }
        }
    }

    public static void StopStorageEmulator()
    {
        using (Process process = Process.Start(stopStorageEmulator))
        {
            process.WaitForExit();
        }
    }
}

现在我们开始:将字符串“start”传递给方法ExecuteWAStorageEmulator()。 Framework仅用于断言

using System.Diagnostics;
using NUnit.Framework;

private static void ExecuteWAStorageEmulator(string argument)
{
    var start = new ProcessStartInfo
    {
        Arguments = argument,
        FileName = @"c:\Program Files (x86)\Microsoft SDKs\Windows Azure\Storage Emulator\WAStorageEmulator.exe"
    };
    var exitCode = ExecuteProcess(start);
    Assert.AreEqual(exitCode, 0, "Error {0} executing {1} {2}", exitCode, start.FileName, start.Arguments);
}

private static int ExecuteProcess(ProcessStartInfo start)
{
    int exitCode;
    using (var proc = new Process { StartInfo = start })
    {
        proc.Start();
        proc.WaitForExit();
        exitCode = proc.ExitCode;
    }
    return exitCode;
}

另请参见我的新自答

v4.6中的文件名为“AzureStorageEmulator.exe”。完整路径是:“C:\Program Files(x86)\Microsoft SDK\Azure\Storage Emulator\AzureStorageEmulator.exe”

对于Windows Azure Storage Emulator v5.2,可以使用以下帮助程序类启动仿真器:

using System.Diagnostics;

public static class StorageEmulatorHelper {
    /* Usage:
     * ======
       AzureStorageEmulator.exe init            : Initialize the emulator database and configuration.
       AzureStorageEmulator.exe start           : Start the emulator.
       AzureStorageEmulator.exe stop            : Stop the emulator.
       AzureStorageEmulator.exe status          : Get current emulator status.
       AzureStorageEmulator.exe clear           : Delete all data in the emulator.
       AzureStorageEmulator.exe help [command]  : Show general or command-specific help.
     */
    public enum StorageEmulatorCommand {
        Init,
        Start,
        Stop,
        Status,
        Clear
    }

    public static int StartStorageEmulator() {
        return ExecuteStorageEmulatorCommand(StorageEmulatorCommand.Start);
    }

    public static int StopStorageEmulator() {
        return ExecuteStorageEmulatorCommand(StorageEmulatorCommand.Stop);
    }

    public static int ExecuteStorageEmulatorCommand(StorageEmulatorCommand command) {
        var start = new ProcessStartInfo {
            Arguments = command.ToString(),
            FileName = @"C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe"
        };
        var exitCode = executeProcess(start);
        return exitCode;
    }

    private static int executeProcess(ProcessStartInfo startInfo) {
        int exitCode = -1;
        try {
            using (var proc = new Process {StartInfo = startInfo}) {
                proc.Start();
                proc.WaitForExit();
                exitCode = proc.ExitCode;
            }
        }
        catch {
            //
        }
        return exitCode;
    }
}

[感谢huha提供了执行shell命令的样板代码。]

现在有一个简洁的小NuGet包,可以帮助以编程方式启动/停止Azure存储模拟器:

源代码在中提供,但您基本上可以执行以下操作:

C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator>WAStorageEmulator.exe status
if(!AzureStorageEmulatorAutomation.IsEmulatorRunning())
{
    AzureStorageEmulatorAutomation emulator = new AzureStorageEmulatorAutomation();
    emulator.Start();

    // Even clear some things
    emulator.ClearBlobs();
    emulator.ClearTables();
    emulator.ClearQueues();

    emulator.Stop();
}

我觉得这是最干净的选择。

谢谢,但事实并非如此。存储仿真器实际上会启动,然后立即崩溃。我编辑了这篇文章以包含应用程序事件日志中的信息。此外,我的第一次尝试确实包括了您建议的“.exe”,但它的行为方式相同。感谢您确认它在您的计算机上工作,但您的代码在我的计算机上以相同的方式崩溃。因此,如果打开命令提示符并运行该代码,csrun会崩溃,但如果您在同一提示符下运行“csrun/devstore”,它会工作吗?真奇怪。什么操作系统?您运行的用户有什么特别之处吗?用户名中有空格吗?这可能与我在这里遇到的问题有关@smarx-如OP中所示,我在单元测试设置期间运行此代码。作为测试,我以单机版的形式运行了你的程序
using System.Diagnostics;

public static class StorageEmulatorHelper {
    /* Usage:
     * ======
       AzureStorageEmulator.exe init            : Initialize the emulator database and configuration.
       AzureStorageEmulator.exe start           : Start the emulator.
       AzureStorageEmulator.exe stop            : Stop the emulator.
       AzureStorageEmulator.exe status          : Get current emulator status.
       AzureStorageEmulator.exe clear           : Delete all data in the emulator.
       AzureStorageEmulator.exe help [command]  : Show general or command-specific help.
     */
    public enum StorageEmulatorCommand {
        Init,
        Start,
        Stop,
        Status,
        Clear
    }

    public static int StartStorageEmulator() {
        return ExecuteStorageEmulatorCommand(StorageEmulatorCommand.Start);
    }

    public static int StopStorageEmulator() {
        return ExecuteStorageEmulatorCommand(StorageEmulatorCommand.Stop);
    }

    public static int ExecuteStorageEmulatorCommand(StorageEmulatorCommand command) {
        var start = new ProcessStartInfo {
            Arguments = command.ToString(),
            FileName = @"C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe"
        };
        var exitCode = executeProcess(start);
        return exitCode;
    }

    private static int executeProcess(ProcessStartInfo startInfo) {
        int exitCode = -1;
        try {
            using (var proc = new Process {StartInfo = startInfo}) {
                proc.Start();
                proc.WaitForExit();
                exitCode = proc.ExitCode;
            }
        }
        catch {
            //
        }
        return exitCode;
    }
}
if(!AzureStorageEmulatorAutomation.IsEmulatorRunning())
{
    AzureStorageEmulatorAutomation emulator = new AzureStorageEmulatorAutomation();
    emulator.Start();

    // Even clear some things
    emulator.ClearBlobs();
    emulator.ClearTables();
    emulator.ClearQueues();

    emulator.Stop();
}