Cannot bind function parameter to type TraceWriter after publishing to Azure - azure

I'm following the guide https://mikhail.io/2017/12/precompiled-azure-functions-in-fsharp/:
Created dotnet f# project: dotnet new classlib --language F# --name HelloFunctions
Added reference to functions: dotnet add package Microsoft.NET.Sdk.Functions
Added a new function as noted in file Library.fs below, added configuration files, etc.
Compiled the function
It successfully starts locally with dotnet build && dotnet publish && cd bin/Debug/netstandard2.0/publish && func start.
Publish it to Azure: func azure functionapp publish <name>
Azure sees the function, it is ok.
When I navigate to function by clicking its name in the tree the error popups:
Function ($Hello) Error: Microsoft.Azure.WebJobs.Host:
Error indexing method 'Functions.Hello'. Microsoft.Azure.WebJobs.Host:
Cannot bind parameter 'log' to type TraceWriter. Make sure the parameter Type
is supported by the binding. If you're using binding extensions (e.g.
ServiceBus, Timers, etc.) make sure you've called the
registration method for the extension(s) in your startup code (e.g.
config.UseServiceBus(), config.UseTimers(), etc.).
The function does not seem to be working. Perhaps because of the error above.
Library.fs
namespace HelloFunctions
open System
open Microsoft.Azure.WebJobs
open Microsoft.Azure.WebJobs.Host
module Say =
let private daysUntil (d: DateTime) =
(d - DateTime.Now).TotalDays |> int
let hello (timer: TimerInfo, log: TraceWriter) =
let christmas = new DateTime(2017, 12, 25)
daysUntil christmas
|> sprintf "%d days until Christmas"
|> log.Info

Sounds very much like assembly version conflict (runtime running one version of Microsoft.Azure.WebJobs.Host.dll, while your app referenced the other).
My guess would be that you compiled your local app with version 2.0 of the runtime, while Azure Function App is configured to 1.0 (default). Please check.

Related

Azure Functions v1 timer triggered function cannot start due to Windows Platform FIPS issue

I'm trying to develop a function app that uses a timer trigger and I'm getting an issue with the Windows Platform FIPS that prevents the timer-triggered function to start locally. Here's the code that's causing the error (it's the default timer-triggered function):
using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Host;
namespace FunctionApp1
{
public static class Function1
{
[FunctionName("Function1")]
public static void Run([TimerTrigger("0 */5 * * * *")]TimerInfo myTimer, TraceWriter log)
{
log.Info($"C# Timer trigger function executed at: {DateTime.Now}");
}
}
}
When I try to run this function in func.exe, it produces the following error:
The listener for function 'Function1' was unable to start. mscorlib: Exception has been thrown by the target of an invocation. mscorlib: This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms.
This exact code works on another dev environment that I have access to. What do I need to do to fix these Windows Platform FIPS issues so that the timer trigger will run?
Thanks!
If your environment does need this FipsAlgorithmPolicy somewhere, disable it for Azure function only.
In File Explorer, open %localappdata%\AzureFunctionsTools\Releases\1.4.0\cli\func.exe.Config, add <enforceFIPSPolicy enabled="false"/> under <runtime> element. Note that in this way, you have to repeat this step once new function cli is released.
Similarly, if you use Storage Emulator locally, open C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe.config, add <enforceFIPSPolicy enabled="false"/> under element.
Else just disable FipsAlgorithmPolicy for your computer.
In search box or right click on Start button and click Run, input regedit to open Registry Editor.
In address bar(View>Address Bar), navigate to Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\FipsAlgorithmPolicy.
Double click on Enabled, change Value data to 0.

The binding type 'serviceBusTrigger' is not registered error in azure functions c# with core tools 2

I open a fresh new azure functions project, my packages are:
Microsoft.Azure.WebJobs 3.0.0-beta4
Microsoft.Azure.WebJobs.ServiceBus 3.0.0-beta4
Microsoft.NET.Sdk.Functions 1.0.7
NETStandardLibrary 2.0.1
I use servicebustrigger and my function code is basic:
public static class Function1
{
[FunctionName("OrderPusherFunction")]
public static Task Run([ServiceBusTrigger("orders","orderpusher", Connection ="ServiceBus")]
string myQueueItem, TraceWriter log)
{
log.Info($"C# Queue trigger function processed: {myQueueItem}");
return Task.CompletedTask;
}
}
I also have:
Azure Functions Core Tools (2.0.1-beta.22) and Function Runtime Version: 2.0.11415.0
When i run, i get "The binding type 'serviceBusTrigger' is not registered" error, and the function does not get triggered. Anyone has an idea? This looks to me as a basic setup..
Basically, in v2 ServiceBus trigger was moved out of the default installation into Extensibility model. You need to register Service Bus binding as an extension as per Binding Extensions Management.
Unfortunately, this is all work-in-progress, as there is a number of issues for Service Bus binding:
Migrate ServiceBus Extension to .NET Core - "Done", but see the comments for which problems still exist
Build failure after installing ExtensionsMetadatGenerator into empty v2 app prevents VS tooling from registering the extension properly
Extensions.json is not updated when "extension install" CLI command executed for service bus extension for CLI issue
My advice would be to stick to v1 for now.

Using In-Proc COM DLL with Azure Function

Is it possible to use an In-Proc COM DLL with Azure Functions?
I am migrating my web service to Azure Functions. One of the components has a dependency on a legacy 32-bit COM DLL. This would normally require the DLL to be regsvr32-ed on the system where it will be used. As that seems not possible with Azure Functions is it possible to use such legacy implementations?
Or would it be necessary to revert to a classic cloud service to support this? (My preference would be use the Consumption service plan and benefit from "serverless" architecture.)
Steps:
Create new Azure Function App
Add new Azure Function (http trigger)
Add reference to 32-bit COM component
Call simple test method on COM component
Run locally - works fine
Publish Azure Function
Open function http path - Azure Function fails
Error log reports exception:
Could not load file or assembly 'Interop.MyCOMLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Exception while executing function: Legacy
Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception
while executing function: Legacy ---> System.IO.FileNotFoundException
: Could not load file or assembly 'Interop.MyCOMLib, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null' or one of its dependencies. The
system cannot find the file specified. at async
Functions.Legacy.Run(HttpRequestMessage req,TraceWriter log) at
System.Runtime.CompilerServices.AsyncTaskMethodBuilder 1.Start[TStateMachine](TStateMachine&
stateMachine) at Functions.Legacy.Run(HttpRequestMessage
req,TraceWriter log) at lambda_method(Closure ,Legacy ,Object[] )
at
Microsoft.Azure.WebJobs.Host.Executors.TaskMethodInvoker 2.InvokeAsync(TReflected
instance,Object[] arguments) at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker 2.InvokeAsync[TReflected,TReturnValue](Object
instance,Object[] arguments) at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker
invoker,ParameterHelper parameterHelper,CancellationTokenSource
timeoutTokenSource,CancellationTokenSource
functionCancellationTokenSource,Boolean throwOnTimeout,TimeSpan
timerInterval,IFunctionInstance instance) at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstance
instance,ParameterHelper parameterHelper,TraceWriter
traceWriter,CancellationTokenSource functionCancellationTokenSource)
at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??)
at async
Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??)
End of inner exception
Also, if I go to the solution's Dependencies | COM then select the Interop.Lib and select to Embed Interop Types then with this change, after publish, on calling the publushed function:
"Retrieving the COM class factory for component with CLSID {D84F92D7-FFFF-4C16-B939-EC98E3A6EBC0} failed due to the following error: 80040154 Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))."
Thus, the challenge is how to register the COM classes with Azure Functions?
It seems that it is not possible to run regsvr32 on function app platform, when running command on Kudu console, it shows "Access Denied".
The solution is to:
1- Create small web service that use COM lib and consume its functionality and host this app on windows VM.
2- Host other part of your you code in function app and instead of reference the function APP to COM , you can call the hosted web service (and pass whatever parameters you want )
Or simply you can deploy full code on VM and don’t use Function APP.
(Thanks to Microsoft support for this answer).
There is nothing special involved in loading a COM object in a process. The process already loads a ton of random windows COM objects already. Give it a try and see if it works.
(not enough reputation to post comments)

Azure DevOps Hosted Build Controller - Is the Azure Storage Emulator supported?

I'd like to run unit / integration tests that utilise the Azure Storage Emulator rather than real storage from a Azure DevOps build.
The emulator is installed on the Hosted Build Controller as part of the Azure SDK in its usual place (C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe).
However the emulator is in the uninitialised state on the Build Controller. When trying to run the command Init from the command line, I get the following error:
This operation requires an interactive window station
Is there an known workaround for this or plans to support the emulator in Azure DevOps builds?
Despite all the answers here to the contrary, I've been running the Azure Storage Emulator on a VS2017 hosted build agent for over a year.
The trick is to initialise SQL LocalDB first (the emulator uses it), and then start the emulator. You can do this with a command line task that runs:
sqllocaldb create MSSQLLocalDB
sqllocaldb start MSSQLLocalDB
sqllocaldb info MSSQLLocalDB
"C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator\AzureStorageEmulator.exe" start
As already stated you can't run the Azure Storage Emulator. What you can run though is Azurite an open source alternative.
Please note: Azurite can emulate blobs, tables and queues. However I have only used the blob storage emulation in this way.
At the start of your build configuration add a nuget step that runs a custom nuget command install Azurite -version 2.2.2. Then add a command line step that runs start /b $(Build.SourcesDirectory)\Azurite.2.2.2\tools\blob.exe.
It runs on the same port as the Azure Storage Emulator so you can use the standard connection strings.
No, the Hosted Build Controller does not run in Interactive Mode, so the emulator won't work under the environment. See Q&A in Hosted build controller for XAML builds for details.
Q: Do you need to run your build service in interactive mode?
A: No. Then you can use the hosted build controller.
I recommend you setup on-premises build controller and run the build server in Interactive Mode. Refer to Setup Build Server and Setup Build Controller for details.
Seems like the answer is maybe from the Visual Studio Online side. There's a User Voice entry if anyone has similar issues.
Not really sure why the emulator doesn't have a non-interactive mode, personally I don't use it's UI 99% of the time. There's a general User Voice entry for making Azure Storage more unit testable.
If you want to do start the Azure Storage Emulator right in your integration test code in C#, you can put this into your test initialization (startup) code (the example is for xUnit):
[Collection("Database collection")]
public sealed class IntegrationTests
{
public IntegrationTests(DatabaseFixture fixture)
{
this.fixture = fixture;
}
[Fact]
public async Task TestMethod1()
{
// use fixture.Table to run tests on the Azure Storage
}
private readonly DatabaseFixture fixture;
}
public class DatabaseFixture : IDisposable
{
public DatabaseFixture()
{
StartProcess("SqlLocalDB.exe", "create MSSQLLocalDB");
StartProcess("SqlLocalDB.exe", "start MSSQLLocalDB");
StartProcess("SqlLocalDB.exe", "info MSSQLLocalDB");
StartProcess(EXE_PATH, "start");
var client = CloudStorageAccount.DevelopmentStorageAccount.CreateCloudTableClient();
Table = client.GetTableReference("tablename");
InitAsync().Wait();
}
public void Dispose()
{
Table.DeleteIfExistsAsync().Wait();
StartProcess(EXE_PATH, "stop");
}
private async Task InitAsync()
{
await Table.DeleteIfExistsAsync();
await Table.CreateAsync();
}
static void StartProcess(string path, string arguments, int waitTime = WAIT_FOR_EXIT) =>
Process.Start(path, arguments).WaitForExit(waitTime);
public CloudTable Table { get; }
private const string EXE_PATH =
"C:\\Program Files (x86)\\Microsoft SDKs\\Azure\\Storage Emulator\\AzureStorageEmulator.exe";
private const int WAIT_FOR_EXIT = 60_000;
}
[CollectionDefinition("Database collection")]
public class DatabaseCollection : ICollectionFixture<DatabaseFixture>
{
// This class has no code, and is never created. Its purpose is simply
// to be the place to apply [CollectionDefinition] and all the
// ICollectionFixture<> interfaces.
}

Unable to Install NServiceBus Host Windows Service

I'm attempting to follow the instructions to install the windows service host using NServiceBus.Host.exe for the VideoStore sample app. I'm following the instructions from the web site.
My application runs fine when doing an F5 session in Visual Studio. It's hosting using the console app mode for the host. When I attempt to use the command line to perform the installation, I get multiple errors.
The command line I'm running is:
NServiceBus.Host.exe /install /serviceName:"VideoStore.Sales"
/displayName:"VideoStore.Sales" /description:"Endpoint for
VideoStore.Sales"
/endpointConfigurationType:"VideoStore.Sales.EndpointConfig,
VideoStore.Sales" /username:".\MySvc" /password:"MyPassword"
NServiceBus.Production
Running this resulted in the following exception:
Initializing the installer in the Install AppDomain
Unhandled Exception: System.InvalidOperationException: Sequence
contains more than one matching element at
System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable1 source,
Func2 predicate) at
System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext() at
System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext() at
System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at
NServiceBus.Hosting.Profiles.ProfileManager..ctor(List1
assembliesToScan, IConfigureThisEndpoint specifier, String[] args,
List`1 defaultProfiles)
It turns out, this error is caused because my application is referencing both the NServiceBus.Host assembly as well as the NServiceBus.Hosting.Azure assembly. This is because my application is being deployed both in a Windows environment as well as to an Azure worker role. I can switch between the azure emulator and the console-mode for worker roles without issue simply by changing which projects i'm starting when debugging. (Azure cloud service project vs each of the worker projects.)
I was able to resolve this by deleting the NServiceBus.Hosting.Azure.dll assembly to prevent the assembly scanning from finding it. IMHO, this is a bug. Either allow me to specify the host type explicitly or handle a scenario where multiple types are found.
This stopped the previous exception, and instead introduced a new one:
Unhandled Exception:
System.Configuration.ConfigurationErrorsException: Command line
argument 'endpointConfigurationType' has specified to use the type
'VideoStore.Sales.EndpointConfig, VideoStore.Sales' but that type
could not be loaded. at
NServiceBus.Hosting.Windows.EndpointTypeDeterminer.TryGetEndpointConfigurationTypeFromArguments(HostArguments
arguments, Type& type) in y:\BuildAgent\work
\31f8c64a6e8a2d7c\src\NServiceBus.Hosting.Windows\EndpointTypeDeterminer.cs:line
101 at NServiceBus.Hosting.Windows.Program.Main(String[] args) in
y:\BuildAgent\work\31f8c64a6e8a2d7c\src\NServiceBus.Hosting.Windows\Program.cs:line
38
Both that type and that assembly exist. I've even verified that .NET is loading the type via enabling fusion loader logging:
The operation was successful. Bind result: hr = 0x0. The operation
completed successfully.
Assembly manager loaded from:
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll Running under
executable
C:\Projects\Testing\NServiceBus.Azure.Samples-master\VideoStore.AzureServiceBus.Cloud\VideoStore.Sales\bin\Debug\NServiceBus.Host.exe
--- A detailed error log follows.
=== Pre-bind state information === LOG: DisplayName = VideoStore.Sales (Partial) WRN: Partial binding information was supplied for an
assembly: WRN: Assembly Name: VideoStore.Sales | Domain ID: 1 WRN: A
partial bind occurs when only part of the assembly display name is
provided. WRN: This might result in the binder loading an incorrect
assembly. WRN: It is recommended to provide a fully specified textual
identity for the assembly, WRN: that consists of the simple name,
version, culture, and public key token. WRN: See whitepaper
http://go.microsoft.com/fwlink/?LinkId=109270 for more information and
common solutions to this issue. LOG: Appbase =
file:///C:/Projects/Testing/NServiceBus.Azure.Samples-master/VideoStore.AzureServiceBus.Cloud/VideoStore.Sales/bin/Debug/
LOG: Initial PrivatePath = NULL LOG: Dynamic Base = NULL LOG: Cache
Base = NULL LOG: AppName = NServiceBus.Host.exe Calling assembly :
NServiceBus.Host, Version=4.6.0.0, Culture=neutral,
PublicKeyToken=9fc386479f8a226c.
What am I doing wrong here?
EDIT
I believe I see the issue. Basically, trying to avoid the first error where NServiceBus is resolving multiple Profiles due to the fact it's finding them in both NServiceBus.Core and NServicebus.Hosting.Azure is causing the second error.
This is because in order to load my EndpointConfig type, .NET also needs to load the NServicebus.Hosting.Azure assembly, as it implements AsA_Worker, which lives in NServiceBus.Hosting.Azure.
So be deleting that assembly, I'm preventing it from loading the EndpointConfig.
I'm still unclear as to how to resolve this. I need to get NServiceBus to stop scanning both hosting assemblies. This suggests that christof13's answer is correct, but I'm unable to get NServiceBus to ignore its own assemblies.
The root cause of this issue is that when NServiceBus enumerates profiles available, it scans all available assemblies and then does a LINQ statement to filter them down by type name.
The problem is that there are two NServiceBus.Production profiles, one defined in the NServiceBus.Host.dll, and one in the NServiceBus.Hosting.Azure assembly. Their type names are identical, and so the LINQ SingleOrDefault fails.
The suggestion to filter the assemblies searched wouldn't work because NServiceBus always loads its own assemblies. The filter only applies to my project's assemblies.
I was able to resolve this by creating a custom profile that doesn't have the same name as any other profile defined in any assemblies in my project. Something like:
public class DualCloudLocalProfile : IProfile {}
public class DualCloudLocalProfileHandler : IHandleProfile<DualCloudLocalProfile>
{
public void ProfileActivated()
{
if (LogManager.LoggerFactory is NullLoggerFactory || LogManager.LoggerFactory == null)
{
Configure.Instance.TraceLogger().ConsoleLogger();
}
}
}
public class CloudProfileLoggingHandler : IConfigureLoggingForProfile<DualCloudLocalProfile>
{
public void Configure(IConfigureThisEndpoint specifier)
{
//nothing for now
}
}
Once this was added into my project, I modified the install command to specify the new profile:
NServiceBus.Host.exe /install /serviceName:"VideoStore.Sales" /displayName:"VideoStore.Sales" /description:"Endpoint for VideoStore.Sales" /endpointConfigurationType:"VideoStore.Sales.EndpointConfig, VideoStore.Sales" /username:".\MySvc" /password:"MyPassword" VideoStore.Sales.DualCloudLocalProfile
This resolved the problem. I can now run the project as a cloud service and a NServiceBus.Host.exe hosted service, as well as deploy via the /install command for the host.
You can try to filter the assemblies with one the following methods
Configure.With(string probeDirectory)
Configure.With(params Assembly[] assemblies)
Configure.With(IEnumerable<Type> typesToScan)
By default I think that nservicebus scans all the assemblies in the folder, so if you filter with only the needed assemblies it will prevent from receiving this kind of error
http://docs.particular.net/nservicebus/the-nservicebus-host

Resources