Closed tomaszkiewicz closed 6 years ago
Hi,
I spent few more hours debugging the problem and here's what I found:
As I supposed the problem relates to error in deserialization. It happens in Store.cs file in the following method:
bool IStore<T>.TryLoad(out T item)
{
try
{
return this.store.TryLoad(out item);
}
catch (Exception)
{
// exception in loading the serialized data
item = default(T);
return false;
}
}
When you breakpoint in catch part you can find out that the exception is:
Message "Unable to find assembly 'Microsoft.Bot.Builder, Version=3.5.5.0, Culture=neutral, PublicKeyToken=null'."
at System.Runtime.Serialization.Formatters.Binary.BinaryAssemblyInfo.GetAssembly()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetType(BinaryAssemblyInfo assemblyInfo, String name)
at System.Runtime.Serialization.Formatters.Binary.ObjectMap..ctor(String objectName, String[] memberNames, BinaryTypeEnum[] binaryTypeEnumA, Object[] typeInformationA, Int32[] memberAssemIds, ObjectReader objectReader, Int32 objectId, BinaryAssemblyInfo assemblyInfo, SizedArray assemIdToAssemblyTable)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryObjectWithMapTyped record)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.ReadObjectWithMapTyped(BinaryHeaderEnum binaryHeaderEnum)
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at Microsoft.Bot.Builder.Internals.Fibers.FormatterStore`1.Microsoft.Bot.Builder.Internals.Fibers.IStore<T>.TryLoad(T& item) in D:\Projekty\BotBuilder\CSharp\Library\Microsoft.Bot.Builder\Fibers\Store.cs:line 65
at Microsoft.Bot.Builder.Internals.Fibers.ErrorResilientStore`1.Microsoft.Bot.Builder.Internals.Fibers.IStore<T>.TryLoad(T& item) in D:\Projekty\BotBuilder\CSharp\Library\Microsoft.Bot.Builder\Fibers\Store.cs:line 108
So BotBuilder cannot deserialize dialog stack because it cannot find... it's own assembly!
I've tried to apply the typical solution for this kind of error by implementing own binder that tries every possible and loaded assembly:
sealed class SearchAssembliesBinder : SerializationBinder
{
private readonly Assembly _currentAssembly;
public SearchAssembliesBinder(Assembly currentAssembly)
{
_currentAssembly = currentAssembly;
}
public override Type BindToType(string assemblyName, string typeName)
{
var assemblyNames = new List<AssemblyName>();
assemblyNames.Add(_currentAssembly.GetName());
assemblyNames.Add(Assembly.GetCallingAssembly().GetName());
assemblyNames.AddRange(_currentAssembly.GetReferencedAssemblies());
assemblyNames.AddRange(AppDomain.CurrentDomain.GetAssemblies().Select(s => s.GetName()));
foreach (AssemblyName an in assemblyNames)
{
var typeToDeserialize = Type.GetType($"{typeName}, {an.FullName}");
if (typeToDeserialize != null)
return typeToDeserialize;
}
return null;
}
}
Unfortunately that doesn't help, but the exception changes to:
Message "Could not load file or assembly 'Microsoft.Bot.Builder, Version=3.5.5.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified."
at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection)
at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
at System.Reflection.Assembly.Load(String assemblyString)
at System.UnitySerializationHolder.GetRealObject(StreamingContext context)
at System.Runtime.Serialization.ObjectManager.ResolveObjectReference(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at Microsoft.Bot.Builder.Internals.Fibers.FormatterStore`1.Microsoft.Bot.Builder.Internals.Fibers.IStore<T>.TryLoad(T& item) in D:\Projekty\BotBuilder\CSharp\Library\Microsoft.Bot.Builder\Fibers\Store.cs:line 101
at Microsoft.Bot.Builder.Internals.Fibers.ErrorResilientStore`1.Microsoft.Bot.Builder.Internals.Fibers.IStore<T>.TryLoad(T& item) in D:\Projekty\BotBuilder\CSharp\Library\Microsoft.Bot.Builder\Fibers\Store.cs:line 144
There's also FusionLog property of the exception:
=== Pre-bind state information ===
LOG: DisplayName = Microsoft.Bot.Builder, Version=3.5.5.0, Culture=neutral, PublicKeyToken=null
(Fully-specified)
LOG: Appbase = file:///C:/Users/luktom/AppData/Local/Azure.Functions.Cli/1.0.0-beta.93/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Users\luktom\AppData\Local\Azure.Functions.Cli\1.0.0-beta.93\func.exe.Config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Users/luktom/AppData/Local/Azure.Functions.Cli/1.0.0-beta.93/Microsoft.Bot.Builder.DLL.
LOG: Attempting download of new URL file:///C:/Users/luktom/AppData/Local/Azure.Functions.Cli/1.0.0-beta.93/Microsoft.Bot.Builder/Microsoft.Bot.Builder.DLL.
LOG: Attempting download of new URL file:///C:/Users/luktom/AppData/Local/Azure.Functions.Cli/1.0.0-beta.93/Microsoft.Bot.Builder.EXE.
LOG: Attempting download of new URL file:///C:/Users/luktom/AppData/Local/Azure.Functions.Cli/1.0.0-beta.93/Microsoft.Bot.Builder/Microsoft.Bot.Builder.EXE.
So I've tired to put Bot Builder function on the paths specified above. That also doesn't help. This time the exception is not caught, but the following is printed on console:
A ScriptHost error has occurred
Exception while executing function: Functions.messages. Bot: The type initializer for 'Microsoft.Bot.Builder.Dialogs.Conversation' threw an exception. Microsoft.Bot.Builder.Autofac: Could not load file or assembly 'Microsoft.Bot.Connector, Version=3.5.3.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Exception while executing function: Functions.messages. Bot: The type initializer for 'Microsoft.Bot.Builder.Dialogs.Conversation' threw an exception. Microsoft.Bot.Builder.Autofac: Could not load file or assembly 'Microsoft.Bot.Connector, Version=3.5.3.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Exception while executing function: Functions.messages
Exception while executing function: Functions.messages. Bot: The type initializer for 'Microsoft.Bot.Builder.Dialogs.Conversation' threw an exception. Microsoft.Bot.Builder.Autofac: Could not load file or assembly 'Microsoft.Bot.Connector, Version=3.5.3.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Executed 'Functions.messages' (Failed, Id=8e221200-0ad4-48a5-91a9-a876780965a4)
mscorlib: Exception while executing function: Functions.messages. Bot: The type initializer for 'Microsoft.Bot.Builder.Dialogs.Conversation' threw an exception. Microsoft.Bot.Builder.Autofac: Could not load file or assembly 'Microsoft.Bot.Connector, Version=3.5.3.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
Function had errors. See Azure WebJobs SDK dashboard for details. Instance ID is '8e221200-0ad4-48a5-91a9-a876780965a4'
mscorlib: Exception while executing function: Functions.messages. Bot: The type initializer for 'Microsoft.Bot.Builder.Dialogs.Conversation' threw an exception. Microsoft.Bot.Builder.Autofac: Could not load file or assembly 'Microsoft.Bot.Connector, Version=3.5.3.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
I hope it helps, I have no idea what I can do next in this case.
I see Connector version 3.5.3.0 and Builder version 3.5.5.0 in your logs - any chance of a assembly version mismatch? From what I understand, Azure Bot Service doesn't support bindingRedirects.
The 2nd post was based on debug branch in which I updated to newest version. I debugged it also with the newest source code of BotFramework from GitHub. I don't know if ABS supports bindingRedirects, but in other Azure Functions I never had any problem with any library, so I suppose it could be supported.
Did you ever figure out a work around for this? I am having a similar issue and have run out of ideas.
Unfortunately not, after 2-3 days of dubugging I opened this issue and switched my project to classic asp.net mvc web app.
When using Azure Bot Service with precompiled .dlls I didn't manage to get nuget dependencies working, but I did find that including all the dependencies (~18 .dll files) in the /bin folder solved my assembly binding exceptions. This is hardly an ideal solution though.
Hi, any news about this issue ? I have a workaround, but I think its really bad...
builder
.Register((c, p) => new FactoryStore<IFiberLoop<DialogTask>>(new MemoryErrorResilientStore<IFiberLoop<DialogTask>>(new FormatterStore<IFiberLoop<DialogTask>>(p.TypedAs<Stream>(), c.Resolve<IFormatter>(p))), c.Resolve<Func<IFiberLoop<DialogTask>>>(p)))
.As<IStore<IFiberLoop<DialogTask>>>()
.InstancePerDependency();
and
public class MemoryErrorResilientStore<T> : IStore<T>
{
static System.Collections.Concurrent.ConcurrentDictionary<string, object> bag = new System.Collections.Concurrent.ConcurrentDictionary<string, object>();
private readonly IStore<T> store;
public MemoryErrorResilientStore(IStore<T> store)
{
SetField.NotNull(out this.store, nameof(store), store);
}
void IStore<T>.Reset()
{
this.store.Reset();
}
bool IStore<T>.TryLoad(out T item)
{
try
{
object obj = null;
bag.TryGetValue(typeof(T).FullName, out obj);
if (obj == null)
{
item = default(T);
return false;
}
item = (T)obj;
return true;
}
catch (Exception ex)
{
// exception in loading the serialized data
item = default(T);
return false;
}
}
void IStore<T>.Save(T item)
{
bag.TryAdd(typeof(T).FullName, item);
}
void IStore<T>.Flush()
{
this.store.Flush();
}
}
Any updates on this? With new azure functions tooling it seems like compilable functions are way to go and this way we can't take advantage of them,
Hi, @AdamMarczak To use the new VS 17 15.3 tooling for Azure function, you have to use https://github.com/Microsoft/BotBuilder-Azure but I found the bug and submit a pull request https://github.com/Microsoft/BotBuilder-Azure/pull/15 to correct the serialization issue
Great news @NicolasHumann! I did use bot builder for azure but I didn't see there's option for storing state. This means deserialization will no longer be an issue, cool!
Thank you @NicolasHumann for your pull request, it pointed me in the right direction. I extended it a little bit to work also for assemblies that are not loaded to the AppDomain yet.
Technically you are not required to use BotBuilder-Azure but it has some features that you would have to implement by yourself. Like the authentication stuff. And I hope it will fix the assembly loading problem in the future.
Until it gets fixed I created my own assembly resolve handler:
public class AzureFunctionsResolveAssembly : IDisposable
{
public AzureFunctionsResolveAssembly()
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
}
void IDisposable.Dispose()
{
AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs arguments)
{
var assembly = AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(a => a.GetName().FullName == arguments.Name);
if (assembly != null)
{
return assembly;
}
// try to load assembly from file
var assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var assemblyName = new AssemblyName(arguments.Name);
var assemblyFileName = assemblyName.Name + ".dll";
string assemblyPath;
if (assemblyName.Name.EndsWith(".resources"))
{
var resourceDirectory = Path.Combine(assemblyDirectory, assemblyName.CultureName);
assemblyPath = Path.Combine(resourceDirectory, assemblyFileName);
}
else
{
assemblyPath = Path.Combine(assemblyDirectory, assemblyFileName);
}
if (File.Exists(assemblyPath))
{
return Assembly.LoadFrom(assemblyPath);
}
return null;
}
}
And this is how I use it in my Azure Functions Bot:
[FunctionName("Messages")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "messages")]HttpRequestMessage req, TraceWriter log)
{
// use custom assembly resolve handler
using(new AzureFunctionsResolveAssembly())
using (BotService.Initialize())
{
// Deserialize the incoming activity
string jsonContent = await req.Content.ReadAsStringAsync();
var activity = JsonConvert.DeserializeObject<Activity>(jsonContent);
// authenticate incoming request and add activity.ServiceUrl to MicrosoftAppCredentials.TrustedHostNames
// if request is authenticated
if (!await BotService.Authenticator.TryAuthenticateAsync(req, new[] { activity }, CancellationToken.None))
{
return BotAuthenticator.GenerateUnauthorizedResponse(req);
}
if (activity != null)
{
switch (activity.GetActivityType())
{
case ActivityTypes.Message:
await Conversation.SendAsync(activity, () => new RootDialog());
break;
[...]
}
}
return req.CreateResponse(HttpStatusCode.Accepted);
}
}
Glad I stumbled across this - I too saw the "Azure Bot Service" thing in the portal was using the csx-style functions and thought I'd be clever by following the same basic pattern but with pre-compiled functions. Basic call-and-response got working quickly, but dialog state just seemed to be disappearing. I even debugged it so far as to confirm that the right state was flowing back and forth to the state server (ie. https://state.botframework.com/v3/botstate/webchat/conversations/XXXX/users/YYYY) - never occurred to me that the deserialization was where the problem was.
Thanks to @NicolasHumann and @berhir though, I have this working now (at least locally in the emulator). Looking forward to continuing to see how this develops.
In addition to fixing it (obviously), is there a good reason exceptions on deserialization should be silently swallowed? Shouldn't we get some way to hook into them? Are there other similar places where things might fail silently? Maybe a custom interface implementation we can provide to the AutoFac config? Or at least have something writing to the console about the possible issue.
Open a new issue if further questions
I was having the same problem using binary serialization through a storage queue. When attempting to deserialize the message with the BinaryFormatter the assembly containing the class would get the "could not find assembly exception". Even though an instance of the class had already been created previously. The fusion loader recorded no bind failures so I was stuck until I found this post. I used the assembly resolver code posted by berhir and now the serialization is working. Thanks!
This sounds like a very old issue with the way some EXEs host the .NET runtime. Way back in time it was often COM+ or IE and then Cassini that had this issue. Long ago (2002 or so?) I wrote a workaround for the issue that you can hook into your AppDomain only once to provide a custom resolver for the assembly resolution failure. It is in this old chunk of code:
https://github.com/MarimerLLC/csla/blob/V1-5-x/cslacs10/NetRun/Launcher.cs#L49
Thanks for the feedback. I updated my C# function to include the assembly resolver but get the same exception.
Ling Toh posted the following in the forum:
Loading native assemblies is currently not supported in Azure Functions. Kindly see, https://github.com/Azure/Azure-Functions/issues/622
Although that issue as far as I see nor anywhere else in all the docs of Azure Functions do I see a definitive statement that loading unmanaged assemblies is not supported. I do see several questions about how to do it and MS techs trying to figure it out. I would suggest adding a clear statement in the sand box restrictions.
Thanks again
Invocation details
Parameter
req
Method: GET, Uri: https://unfunction.azurewebsites.net/api/UnAdder/val1/5/val2/6
val1
5
val2
6
log
$return
response
Failure
Could not load file or assembly 'UnAdderWrapper.DLL' or one of its dependencies. The specified module could not be found.
Logs
Exception while executing function: UnAdder
Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception while executing function: UnAdder ---> System.IO.FileNotFoundException : Could not load file or assembly 'UnAdderWrapper.DLL' or one of its dependencies. The specified module could not be found.
at UnFunction.UnAdder.Run(HttpRequestMessage req,Int32 val1,Int32 val2,TraceWriter log)
at lambda_method(Closure ,UnAdder ,Object[] )
at Microsoft.Azure.WebJobs.Host.Executors.MethodInvokerWithReturnValue`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
using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Reflection;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using UnAdderWrapper;
namespace UnFunction
{
public static class UnAdder
{
[FunctionName("UnAdder")]
public static HttpResponseMessage
Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "UnAdder/val1/{val1}/val2/{val2}")]HttpRequestMessage req, int val1, int val2, TraceWriter log)
{
SerializationWorkaround();
log.Info("C# HTTP trigger function processed a request.");
// Fetching the name from the path parameter in the request URL
Adder aw = new Adder();
int sum = aw.Sum(val1, val2);
return req.CreateResponse(HttpStatusCode.OK, $"Hello Sum={sum}");
}
#region Serialization bug workaround
private static void SerializationWorkaround()
{
// hook up the AssemblyResolve
// event so deep serialization works properly
// this is a workaround for a bug in the .NET runtime
AppDomain.CurrentDomain.AssemblyResolve +=
new System.ResolveEventHandler(ResolveEventHandler);
}
private static Assembly ResolveEventHandler(object sender,
ResolveEventArgs e)
{
// get a list of all the assemblies loaded in our appdomain
Assembly[] list = AppDomain.CurrentDomain.GetAssemblies();
// search the list to find the assemby that was not found
automatically
// and return the assembly from the list
foreach (Assembly asm in list)
if (asm.FullName == e.Name)
return asm;
// we didn't find it either, so return null
return null;
}
}
}
From: Rockford Lhotka [mailto:notifications@github.com] Sent: Sunday, April 01, 2018 11:32 AM To: Microsoft/BotBuilder Cc: David; Comment Subject: Re: [Microsoft/BotBuilder] Deserialization doesn't work when invoked from Azure Function (#2407)
This sounds like a very old issue with the way some EXEs host the .NET runtime. Way back in time it was often COM+ or IE and then Cassini that had this issue. Long ago (2002 or so?) I wrote a workaround for the issue that you can hook into your AppDomain only once to provide a custom resolver for the assembly resolution failure. It is in this old chunk of code:
https://github.com/MarimerLLC/csla/blob/V1-5-x/cslacs10/NetRun/Launcher.cs
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Microsoft/BotBuilder/issues/2407#issuecomment-377798727, or mute the thread https://github.com/notifications/unsubscribe-auth/AFMURAOMRaF5UNKKT5xe90OPQhwWqbLPks5tkQEPgaJpZM4MX58D .
Hi,
I setup a bot on Azure Bot Service, downloaded the template, made it work with VS2015 and I've moved all code to separate class library to run it as precompiled function.
You can find whole code here: https://github.com/tomaszkiewicz/AzureFunctionsPersistenceProblem/tree/test
So, my function.json file looks like this:
The Bot.Runner.Run function is the same as it was from the template and I do the following on new message:
await Conversation.SendAsync(activity, () => new BasicProactiveEchoDialog());
So it's typical calling of dialogs stack. At this step I am able to chat with the bot (tested both on emulator and on Azure Bot Service) so everything is loaded correctly etc.
The problem is that this dialog is not deserialized properly when it's in the separate class library. It worked when it was a .csx file in Azure Function, it also works when I move it to BotApplication template project (the one based on ASP.NET MVC), but as soon as it gets into separate class library everything breaks.
I've tried to gather more details, so I've added both parameterless constructor and a method with OnDeserialize attribute, put a breakpoint in each of them and the behaviour is that OnDeserialize method gets invoked, when I lookup in the count variable in this dialog it is correctly deserialized but... after I resume the execution the parameterless constructor gets called.
I've found in documentation or stackoverflow thread (I don't remember excactly where) that the behaviour of bot framework is that if it is not possible to sucessfully deserialize the dialog stack it gets resetted. So it's probably that case here, but I cannot find a reason of unsucessful deserialization...
Could you take a look at it? Or maybe suggest what to check to provide more details?
Best regards
Łukasz Tomaszkiewicz