如何从程序中启动Azure存储模拟器
我有一些使用Azure存储的unit testing。 在本地运行这些时,我希望它们使用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,时间戳:0x4d8cdb54exception代码:0xc0000005故障偏移:0x00000000001de8d4故障处理id:0x%9错误应用程序启动时间:0x%10错误应用程序路径:%11错误模块路径:%12报告ID:%13
2015年1月19日更新:
在进行了更多测试(即运行多个版本)之后,我发现WAStorageEmulator.exe
的状态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.exe
的状态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(); } } }
这个程序对我来说很好。 试一试,如果它也适合你,那就从那里开始工作吧。 (你的应用程序与此有何不同?)
using System.Diagnostics; public class Program { public static void Main() { Process.Start(@"c:\program files\windows azure sdk\v1.5\bin\csrun", "/devstore").WaitForExit(); } }
对于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命令的样板代码。]
仅供参考 – 1.6默认位置是MSDN文档中所述的C:\ Program Files \ Windows Azure Emulator \ emulator。
我们遇到了同样的问题。 我们有一个“冒烟测试”的概念,它在各组测试之间运行,并确保在下一组开始之前环境处于良好状态。 我们有一个.cmd文件启动了冒烟测试,它可以很好地启动devfabric模拟器,但只有.cmd进程运行时,devstore模拟器才会运行。
显然,DSServiceSQL.exe的实现与DFService.exe不同。 DFService似乎像Windows服务一样运行 – 启动它,它继续运行。 一旦启动它的进程死亡,DSServiceSQL就会死掉。
v4.6中的文件名是“AzureStorageEmulator.exe”。 完整路径是:“C:\ Program Files(x86)\ Microsoft SDKs \ Azure \ Storage Emulator \ AzureStorageEmulator.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(); } }
可能是由于找不到文件引起的?
试试这个
FileName = Path.Combine(SDKDirectory, "csrun.exe")
我们继续:将字符串“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; }
另见我的新自答问题