Пример #1
0
 private static bool ValidateCalculationRequestMessage(CalculationRequestMessage crm)
 {
     if (String.IsNullOrEmpty(crm.RequestId))
     {
         throw new Exception("RequestId cannot be null or empty");
     }
     if (String.IsNullOrEmpty(crm.FunctionName))
     {
         throw new Exception("Function Name cannot be null or empty");
     }
     if (String.IsNullOrEmpty(crm.DllName))
     {
         throw new Exception("Dll Name cannot be null or empty");
     }
     if (String.IsNullOrEmpty(crm.ContainerName))
     {
         throw new Exception("Container Name cannot be null or empty");
     }
     return(true);
 }
Пример #2
0
        private static async Task ProcessCalculationRequest(CalculationRequestMessage crm)
        {
            var calculationResponseMessage = new CalculationResponseMessage(crm);

            Console.WriteLine($"ProcessingCalculationRequest at {DateTime.Now.ToShortTimeString()}");
            Console.WriteLine($"Request: {crm}");
            Console.WriteLine($"Current Directory: {Directory.GetCurrentDirectory()}");
            if (ValidateCalculationRequestMessage(crm))
            {
                calculationResponseMessage.CalculationRequestStatus = CalculationRequestStatus.InProgress;
            }

            ConsoleWriteInColour($"Downloading DLL...{crm.DllName} from container {crm.ContainerName}", ConsoleColor.Green);
            string             dllFileName;
            var                storageAccount = CloudStorageAccount.Parse(storageConnectionString);
            CloudBlobClient    blobClient     = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer container      = blobClient.GetContainerReference(crm.ContainerName);

            try
            {
                Console.WriteLine($"Current directory={Directory.GetCurrentDirectory()}");
                var directoryToCreate = $"{Directory.GetCurrentDirectory()}\\dll";
                Directory.CreateDirectory(directoryToCreate);
                Console.WriteLine($"directory {directoryToCreate} was created");
                dllFileName = $"{directoryToCreate}\\{crm.DllName}";

                var dllBlob = container.GetBlockBlobReference(crm.DllName);
                await dllBlob.FetchAttributesAsync();

                Console.WriteLine($"Blob {crm.DllName} in container {crm.ContainerName} is {dllBlob.Properties.Length} bytes");
                var memoryStream = new MemoryStream();
                await dllBlob.DownloadToStreamAsync(memoryStream);

                using (memoryStream)
                {
                    var fileStream = File.Create(dllFileName);
                    memoryStream.Position = 0;
                    memoryStream.CopyTo(fileStream);
                    fileStream.Close();
                }
                Console.WriteLine($"{crm.DllName} was downloaded to local file system {directoryToCreate}");
                Console.WriteLine($"Directrory Listing:");
                var files = Directory.GetFiles(directoryToCreate);
                foreach (var fileName in files)
                {
                    var fileInfo = new FileInfo($"{fileName}");
                    Console.WriteLine($"Name={fileInfo.Name}, length={fileInfo.Length}");
                }
            }
            catch (Exception e)
            {
                throw new Exception($"Error downloading DLL {crm.DllName} from container {crm.ContainerName}.  Message:{e.Message}", e);
            }
            IntPtr hModule = IntPtr.Zero;

            try
            {
                ConsoleWriteInColour($"DLL Load path is {dllFileName}", ConsoleColor.Green);
                // call a function in the DLL
                hModule = LoadLibrary(dllFileName);
                if (hModule == IntPtr.Zero)
                {
                    int errorCode = Marshal.GetLastWin32Error();
                    throw new Exception($"Failed to load library {dllFileName} (ErrorCode: {errorCode})");
                }
                ConsoleWriteInColour($"{DateTime.Now.ToString()} library {dllFileName} was loaded sucessfully. hModule={hModule}", ConsoleColor.Yellow);

                IntPtr funcaddr = GetProcAddress(hModule, crm.FunctionName);
                if (funcaddr == IntPtr.Zero)
                {
                    int errorCode = Marshal.GetLastWin32Error();
                    throw new Exception($"Failed to find function {crm.FunctionName} (ErrorCode: {errorCode})");
                }
                ConsoleWriteInColour($"{DateTime.Now.ToString()} function {crm.FunctionName} found in library {dllFileName} address={funcaddr}", ConsoleColor.Yellow);

                if (crm.FunctionType == FunctionType.StringFunction)
                {
                    NicksStringFunction stringFunction = Marshal.GetDelegateForFunctionPointer <NicksStringFunction>(funcaddr) as NicksStringFunction;
                    IntPtr stringResultPtr             = stringFunction();
                    string stringResult = Marshal.PtrToStringBSTR(stringResultPtr);
                    ConsoleWriteInColour($"{DateTime.Now.ToString()} function {crm.FunctionName} returned \"{stringResult}\"", ConsoleColor.Cyan);
                    calculationResponseMessage.CalculationRequestStatus = CalculationRequestStatus.Succeeded;
                    calculationResponseMessage.Result = stringResult;
                }

                if (crm.FunctionType == FunctionType.IntFunction)
                {
                    if (Int32.TryParse(crm.Parameters[0], out Int32 number))
                    {
                        IntPtr           numPointer   = new IntPtr(number);
                        NicksIntFunction intFunction  = Marshal.GetDelegateForFunctionPointer <NicksIntFunction>(funcaddr) as NicksIntFunction;
                        IntPtr           intResultPtr = intFunction(numPointer);
                        Int32            intResult    = intResultPtr.ToInt32();
                        ConsoleWriteInColour($"{DateTime.Now.ToString()} function {crm.FunctionName} returned \"{intResult}\"", ConsoleColor.Cyan);
                        calculationResponseMessage.CalculationRequestStatus = CalculationRequestStatus.Succeeded;
                        calculationResponseMessage.Result = intResult.ToString();
                    }
                    else
                    {
                        ConsoleWriteInColour($"{DateTime.Now.ToString()} function {crm.FunctionName} no parameters supplied for function", ConsoleColor.Red);
                    }
                }


                Console.WriteLine($"{DateTime.Now.ToString()} request {crm.RequestId} was processed successfully.");
            }
            catch (Exception e)
            {
                throw new Exception($"Error loading and executing function {crm.FunctionName} from DLL {crm.DllName}.  Message:{e.Message}", e);
            }
            finally
            {
                if (hModule != IntPtr.Zero)
                {
                    FreeLibrary(hModule);
                    ConsoleWriteInColour($"{DateTime.Now.ToString()} library {dllFileName} was unloaded", ConsoleColor.Yellow);
                }
                ;
            }
            // Now serialize the result object to blob storage
            try
            {
                var resultsBlob = container.GetBlockBlobReference($"{crm.RequestId}.json");
                var results     = JsonConvert.SerializeObject(calculationResponseMessage);
                await resultsBlob.UploadTextAsync(results);
            }
            catch (Exception e)
            {
                throw new Exception($"Error uploading results to blob storage.  Function {crm.FunctionName} in DLL {crm.DllName} was called sucessfully.  Message:{e.Message}", e);
            }
        }
Пример #3
0
        public static async Task <int> Main(string[] args)
        {
            var configBuilder = new ConfigurationBuilder()
                                .SetBasePath(Directory.GetCurrentDirectory())
                                .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                                .AddJsonFile("settings.json", optional: true, reloadOnChange: true)
                                .AddEnvironmentVariables();

            IConfiguration configuration = configBuilder.Build();

            var rootCommand = new RootCommand
            {
                new Option <string>(
                    "--messageType",
                    getDefaultValue: () => "CalculateMessage",
                    description: "The type of message to send.  Valid values are QuitMessage and CalculateMessage.  If not supplied this will defualt to CalculateMessage"),
                new Option <string>(
                    "--dllName",
                    description: "The name of the DLL from which you wish to execute a function (DLL will be downloaded from blob storage)"),
                new Option <string>(
                    "--functionName",
                    description: "the name of the function your wish to execute"),
                new Option <string>(
                    "--functionType",
                    description: "The type of function you wish to execute.  Valid values are IntFunction or StringFunction.  If you specify IntFunction you will need to supply a parameter which will be parsed as an integer"),
                new Option <string>(
                    "--parameters",
                    getDefaultValue: () => null,
                    description: "A comma separated string of Int parameters.  Must be supplied for IntFunction calls, ignored for StringFunctions.  "),
            };

            rootCommand.Description = "This command will generate a single calculation request based on the supplied input parameters, and will generate a calculation request message.  " +
                                      "This will be placed on the configured service bus queue, which will then be picked up by the DLLStuff service and the requested calculation performed.  " +
                                      "Finally, the results will be written to the blob storage container specified in configuration.  You can see the results in a blob called <requestid>.json.  " +
                                      "Request Id is written to the console on completion of the command.";
            try
            {
                rootCommand.Handler = CommandHandler.Create <string, string, string, string, string>(async(messageType, dllName, functionName, functionType, parameters) =>
                {
                    try
                    {
                        if (string.IsNullOrEmpty(messageType))
                        {
                            throw new Exception($"--messageType {messageType} must be provided");
                        }
                        if ((messageType.ToLower() != "quitmessage") && (messageType.ToLower() != "calculatemessage"))
                        {
                            throw new Exception($"--messageType {messageType} is invalid.  Valid values are QuitMessage and CalculateMessage");
                        }
                        Console.WriteLine($"The value for --messageType is: {messageType}");


                        if (string.IsNullOrEmpty(dllName))
                        {
                            throw new Exception($"--dllName {dllName} must be provided");
                        }
                        Console.WriteLine($"The value for --dllName is: {dllName}");


                        if (string.IsNullOrEmpty(functionName))
                        {
                            throw new Exception($"--functionName {functionName} must be provided");
                        }
                        Console.WriteLine($"The value for --functionName is: {functionName}");


                        if (string.IsNullOrEmpty(functionType))
                        {
                            throw new Exception($"--functionType {functionType} must be provided");
                        }
                        if ((functionType.ToLower() != "intfunction") && (functionType.ToLower() != "stringfunction"))
                        {
                            throw new Exception($"--messageType {messageType} is invalid.  Valid values are IntFunction and StringFunction");
                        }
                        Console.WriteLine($"The value for --functionType is: {functionType}");

                        if (functionType.ToLower() == "intfunction")
                        {
                            if (string.IsNullOrEmpty(parameters))
                            {
                                throw new Exception($"--parameters {parameters} must be provided when --functionType is {functionType}");
                            }
                        }
                        Console.WriteLine($"The value for --parameters is: {parameters}");


                        string serviceBusConnectionString = "";
                        string serviceBusQueueName        = "";
                        string storageConnectionString    = "";
                        string containerName = "";
                        try
                        {
                            storageConnectionString    = configuration["StorageConnectionString"];
                            serviceBusConnectionString = configuration["ServiceBusConnectionString"];
                            serviceBusQueueName        = configuration["ServiceBusQueueName"];
                            containerName = configuration["ContainerName"];
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine($"Exception caught while accessing configuration: {e.Message}");
                            return;
                        }

                        queueClient       = new QueueClient(serviceBusConnectionString, serviceBusQueueName);
                        var crm           = new CalculationRequestMessage();
                        crm.RequestId     = Guid.NewGuid().ToString();
                        crm.ContainerName = containerName;

                        if (messageType.ToLower() == "quitmessage")
                        {
                            crm.MessageType = MessageType.QuitMessage;
                        }
                        else
                        {
                            crm.MessageType  = MessageType.CalculateMessage;
                            crm.DllName      = dllName;
                            crm.FunctionName = functionName;

                            if (functionType.ToLower() == "stringfunction")
                            {
                                crm.FunctionType = FunctionType.StringFunction;
                            }
                            else
                            {
                                crm.FunctionType = FunctionType.IntFunction;
                                crm.Parameters   = parameters.Split(',');
                            }
                        }

                        var body    = JsonConvert.SerializeObject(crm).ToString();
                        var message = new Message(Encoding.UTF8.GetBytes(body));

                        Console.WriteLine($"Sending message: {body}");
                        await queueClient.SendAsync(message);
                        await queueClient.CloseAsync();
                        Console.ForegroundColor = ConsoleColor.Yellow;
                        Console.WriteLine($"Done. Your request id was {crm.RequestId}");
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }
                                                                                                     );
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return(-1);
            }
            return(rootCommand.InvokeAsync(args).Result);
        }