How to start Azure Storage Emulator from within a program
Asked Answered
M

10

25

I have some unit tests that use Azure Storage. When running these locally, I want them to use the Azure Storage emulator which is part of the Azure SDK v1.5. If the emulator isn't running, I want it to be started.

To start the emulator from the command line, I can use this:

"C:\Program Files\Windows Azure SDK\v1.5\bin\csrun" /devstore

This works fine.

When I try to start it using this C# code, it crashes:

using System.IO;
using System.Diagnostics;
...
ProcessStartInfo processToStart = new ProcessStartInfo() 
{   
    FileName = Path.Combine(SDKDirectory, "csrun"),
    Arguments = "/devstore"
};
Process.Start(processToStart);

I've tried fiddling with a number of ProcessStartInfo settings, but nothing seems to work. Is anybody else having this problem?

I've checked the Application Event Log and found the following two entries:

Event ID: 1023 .NET Runtime version 2.0.50727.5446 - Fatal Execution Engine Error (000007FEF46B40D2) (80131506)

Event ID: 1000 Faulting application name: DSService.exe, version: 6.0.6002.18312, time stamp: 0x4e5d8cf3 Faulting module name: mscorwks.dll, version: 2.0.50727.5446, time stamp: 0x4d8cdb54 Exception code: 0xc0000005 Fault offset: 0x00000000001de8d4 Faulting process id: 0x%9 Faulting application start time: 0x%10 Faulting application path: %11 Faulting module path: %12 Report Id: %13

Masorete answered 25/9, 2011 at 18:20 Comment(0)
M
0

I uninstalled all of the Windows Azure bits:

  • WA SDK v1.5.20830.1814
  • WA Tools for Visual Studio: v1.5.40909.1602
  • WA AppFabric: v1.5.37
  • WA AppFabric: v2.0.224

Then, I downloaded and installed everything using the unified installer. Everything came back except the AppFabric v2. All the version numbers are the same. Reran my tests and still having a problem.

And then...(this is weird)...it would work every now and then. Rebooted the machine and now it works. Have shutdown and rebooted a number of times now...and it just works. (sigh)

Thanks to everyone who provided feedback and/or ideas!

The final code is:

    static void StartAzureStorageEmulator()
    {
        ProcessStartInfo processStartInfo = new ProcessStartInfo()
        {
            FileName = Path.Combine(SDKDirectory, "csrun.exe"),
            Arguments = "/devstore",
        };
        using (Process process = Process.Start(processStartInfo))
        {
            process.WaitForExit();
        }
    }
Masorete answered 30/9, 2011 at 13:40 Comment(0)
A
27

Updated 7/12/2022:

If you are running Visual Studio 2022, azurite.exe is the replacement for the now-deprecated AzureStorageEmulator.exe which can be found here:

C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\Extensions\Microsoft\Azure Storage Emulator\azurite.exe

NB: if you are running Professional (or another) Edition, you'll need to replace Community with Professional (or the appropriate edition name) in the path.

Updated 1/19/2015:

After doing more testing (i.e., running several builds), I've discovered that WAStorageEmulator.exe's status API is actually broken in a couple of significant ways (which may or may not have impact on how you use it).

The status reports False even when an existing process is running if the user differs between the existing running process and the user used to launch the status process. This incorrect status report will lead to a failure to launch the process that looks like this:

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.

Additionally, the status command appears only to report the endpoints specified in WAStorageEmulator.exe.config, not those of the existing running process. I.e., if you start the emulator, then make a change to the config file, and then call status, it will report the endpoints listed in the config.

Given all of these caveats, it may, in fact, simply be better to use the original implementation as it appears to be more reliable.

I will leave both so others can choose whichever solution works for them.

Updated 1/18/2015:

I have fully rewritten this code to properly leverage WAStorageEmulator.exe's status API per @RobertKoritnik's request.

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

And the corresponding tests:

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

Original post:

I took Doug Clutter's and Smarx's code one step further and created a utility class:

The code below has been updated to work on both Windows 7 and 8 and now points at the new storage emulator path as of 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();
        }
    }
}
Adorn answered 7/8, 2013 at 4:26 Comment(4)
This would be even better if you used WAStorageEmulator status instead of checking whether process is running. It would make it OS version independent (regardless how process is named) and future proof in case process name changes in the future (i.e. Windows 10).Carnage
Agreed. I didn't have the time to figure out how to capture and parse the output. Feel free to edit my answer or post a new one!Adorn
@RobertKoritnik unfortunately, it appears that the status API is of limited use in the real world... see my updated answer.Adorn
@DavidPeden the original worked perfect for me, thank you!! only thing I had to add - I've set UseShellExecute = false for ProcessStartInfo configurations as it was failing when being called from under Global.asax.cs, and you already have that set under new implementation.Hannah
C
4

This program worked fine for me. Give it a try, and if it works for you too, work backwards from there. (What about your app is different from this?)

using System.Diagnostics;
public class Program
{
public static void Main() {
        Process.Start(@"c:\program files\windows azure sdk\v1.5\bin\csrun", "/devstore").WaitForExit();
    }
}
Compo answered 25/9, 2011 at 21:49 Comment(5)
Thanks for confirming it works on your machine, but your code crashes in the same way on my machine.Masorete
So if you open up a command prompt and run that code, csrun crashes, but if you run "csrun /devstore" from the same prompt, it works? That's really strange. What OS? Anything special about the user you're running as?Compo
does the username have a space in it? This could be related to the problem I have been having here... #7481410Subscribe
@smarx - As indicated in the OP, I am running this code during the Unit Test setup. As a test, I ran your program as a stand-alone console app and it works just fine. Obviously, something is happening when I run the unit tests, but I haven't a clue what it might be nor why it would cause the crash.Masorete
@DavidSteele - Thanks for the suggestion David. No space in the username.Masorete
T
2

The file name in v4.6 is "AzureStorageEmulator.exe". The full path is: "C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe"

Thera answered 3/2, 2017 at 9:32 Comment(0)
D
2

For Windows Azure Storage Emulator v5.2, the following helper class can be used to start the emulator:

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

[Thanks to huha for the boilerplate code to execute a shell command.]

Denunciation answered 18/12, 2017 at 7:54 Comment(0)
M
1

FYI - The 1.6 default location is C:\Program Files\Windows Azure Emulator\emulator as stated on the MSDN docs.

Mastermind answered 22/12, 2011 at 20:31 Comment(1)
And now (v1.8) it's moved again: C:\Program Files\Microsoft SDKs\Windows Azure\Emulator\csrun.exeZymometer
S
1

We are running into the same issue. We have the concept of a "smoke test" which runs between groups of tests, and which ensure the environment is in a good state before the next group starts. We have a .cmd file that kicks off the smoke tests, and it works just fine starting the devfabric emulator, but the devstore emulator only runs as long as the .cmd process runs.

Apparently the implementation of the DSServiceSQL.exe is different than DFService.exe. DFService seems to run like a windows service - kick it off, and it keeps running. DSServiceSQL dies as soon as the process that started it dies.

Sabir answered 7/2, 2013 at 23:2 Comment(1)
I had to add an extra parameter to the processStartInfo - UseShellExecute = false - an exception message told me to add it, and seemingly it now works.Contango
B
0

maybe caused by file not found?

try this

FileName = Path.Combine(SDKDirectory, "csrun.exe")
Bullion answered 25/9, 2011 at 18:25 Comment(1)
Thanks but that's not the case. The Storage Emulator actually starts and then immediately crashes. I edited the post to include information from the Application Event Log. Also, my first attempt did include the ".exe" as you suggested, but it behaved the same way.Masorete
M
0

I uninstalled all of the Windows Azure bits:

  • WA SDK v1.5.20830.1814
  • WA Tools for Visual Studio: v1.5.40909.1602
  • WA AppFabric: v1.5.37
  • WA AppFabric: v2.0.224

Then, I downloaded and installed everything using the unified installer. Everything came back except the AppFabric v2. All the version numbers are the same. Reran my tests and still having a problem.

And then...(this is weird)...it would work every now and then. Rebooted the machine and now it works. Have shutdown and rebooted a number of times now...and it just works. (sigh)

Thanks to everyone who provided feedback and/or ideas!

The final code is:

    static void StartAzureStorageEmulator()
    {
        ProcessStartInfo processStartInfo = new ProcessStartInfo()
        {
            FileName = Path.Combine(SDKDirectory, "csrun.exe"),
            Arguments = "/devstore",
        };
        using (Process process = Process.Start(processStartInfo))
        {
            process.WaitForExit();
        }
    }
Masorete answered 30/9, 2011 at 13:40 Comment(0)
A
0

Here we go: Pass the string "start" to the method ExecuteWAStorageEmulator(). The NUnit.Framework is used for the Assert only.

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

See also my new self-answered question

Avelin answered 8/4, 2014 at 13:2 Comment(0)
A
0

There's now a neat little NuGet package to assist with starting/stopping the Azure Storage Emulator programmatically: RimDev.Automation.StorageEmulator.

The source code is available in this GitHub repository, but you can essentially do things like this:

if(!AzureStorageEmulatorAutomation.IsEmulatorRunning())
{
    AzureStorageEmulatorAutomation emulator = new AzureStorageEmulatorAutomation();
    emulator.Start();

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

    emulator.Stop();
}

It feels like the cleanest option to me.

Apnea answered 22/7, 2019 at 6:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.