【问题标题】:How to start Azure Storage Emulator from within a program如何从程序中启动 Azure 存储模拟器
【发布时间】:2011-11-24 17:50:00
【问题描述】:

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

要从命令行启动模拟器,我可以使用这个:

"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

【问题讨论】:

    标签: c# azure azure-storage


    【解决方案1】:

    2015 年 1 月 19 日更新:

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

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

    C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator>WAStorageEmulator.exe status
    
    Windows Azure Storage Emulator 3.4.0.0 command line tool
    IsRunning: False
    BlobEndpoint: http://127.0.0.1:10000/
    QueueEndpoint: http://127.0.0.1:10001/
    TableEndpoint: http://127.0.0.1:10002/
    
    C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator>WAStorageEmulator.exe start
    
    Windows Azure Storage Emulator 3.4.0.0 command line tool
    Error: Port conflict with existing application.
    

    此外,status 命令似乎只报告WAStorageEmulator.exe.config 中指定的端点,而不是现有运行进程的端点。即,如果您启动模拟器,然后对配置文件进行更改,然后调用状态,它将报告配置中列出的端点。

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

    我会留下两个,以便其他人可以选择适合他们的解决方案。

    2015 年 1 月 18 日更新:

    根据@RobertKoritnik 的要求,我已完全重写此代码以正确利用WAStorageEmulator.exestatus API

    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 Clutter 和 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();
            }
        }
    }
    

    【讨论】:

    • 如果您使用 WAStorageEmulator status 而不是检查进程是否正在运行,这会更好。它将使其独立于操作系统版本(无论进程如何命名),并在未来进程名称发生变化(即 Windows 10)时进行验证。
    • 同意。我没有时间弄清楚如何捕获和解析输出。随意编辑我的答案或发布一个新答案!
    • @RobertKoritnik 不幸的是,状态 API 在现实世界中的用途似乎有限......请参阅我的更新答案。
    • @DavidPeden 原版非常适合我,谢谢!!唯一我必须添加的 - 我已经为 ProcessStartInfo 配置设置了 UseShellExecute = false,因为它在从 Global.asax.cs 下调用时失败,并且您已经在新实现下设置了该设置.
    【解决方案2】:

    这个程序对我来说很好用。试一试,如果它也适合您,请从那里向后工作。 (您的应用与此有何不同?)

    using System.Diagnostics;
    public class Program
    {
    public static void Main() {
            Process.Start(@"c:\program files\windows azure sdk\v1.5\bin\csrun", "/devstore").WaitForExit();
        }
    }
    

    【讨论】:

    • 感谢您确认它在您的机器上运行,但您的代码在我的机器上以同样的方式崩溃。
    • 因此,如果您打开命令提示符并运行该代码,csrun 会崩溃,但如果您在同一提示符下运行“csrun /devstore”,它会起作用吗?这真的很奇怪。什么操作系统?你运行的用户有什么特别之处吗?
    • 用户名中是否有空格?这可能与我在这里遇到的问题有关...stackoverflow.com/questions/7480910/…
    • @smarx - 如 OP 中所示,我在单元测试设置期间运行此代码。作为测试,我将您的程序作为独立的控制台应用程序运行,它运行良好。显然,当我运行单元测试时发生了一些事情,但我不知道它可能是什么,也不知道它为什么会导致崩溃。
    • @DavidSteele - 感谢大卫的建议。用户名中没有空格。
    【解决方案3】:

    对于 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 命令的样板代码。]

    【讨论】:

      【解决方案4】:

      仅供参考 - 1.6 默认位置是 C:\Program Files\Windows Azure Emulator\emulator,如 MSDN docs 所述。

      【讨论】:

      • 现在 (v1.8) 再次移动:C:\Program Files\Microsoft SDKs\Windows Azure\Emulator\csrun.exe
      【解决方案5】:

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

      显然 DSServiceSQL.exe 的实现与 DFService.exe 不同。 DFService 似乎像 Windows 服务一样运行 - 启动它,它会继续运行。只要启动它的进程终止,DSServiceSQL 就会终止。

      【讨论】:

      • 我必须在 processStartInfo 中添加一个额外的参数 - UseShellExecute = false - 一条异常消息告诉我添加它,并且现在看来它可以工作了。
      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        我卸载了所有 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();
                }
            }
        

        【讨论】:

          【解决方案8】:

          可能是找不到文件造成的?

          试试这个

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

          【讨论】:

          • 谢谢,但事实并非如此。 Storage Emulator 实际启动,然后立即崩溃。我编辑了帖子以包含来自应用程序事件日志的信息。此外,我的第一次尝试确实包含了您建议的“.exe”,但它的行为方式相同。
          【解决方案9】:

          我们开始:将字符串“start”传递给方法 ExecuteWAStorageEmulator()。 NUnit.Framework 仅用于 Assert。

          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;
          }
          

          另请参阅我的新自我回答question

          【讨论】:

            【解决方案10】:

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

            源代码在this GitHub repository 中提供,但您基本上可以这样做:

            if(!AzureStorageEmulatorAutomation.IsEmulatorRunning())
            {
                AzureStorageEmulatorAutomation emulator = new AzureStorageEmulatorAutomation();
                emulator.Start();
            
                // Even clear some things
                emulator.ClearBlobs();
                emulator.ClearTables();
                emulator.ClearQueues();
            
                emulator.Stop();
            }
            

            这对我来说是最干净的选择。

            【讨论】:

              猜你喜欢
              • 2021-09-12
              • 2018-12-28
              • 2014-09-09
              • 1970-01-01
              • 2012-07-09
              • 2018-03-27
              • 2017-05-09
              • 1970-01-01
              相关资源
              最近更新 更多