I would like to use gstreamer to display udpsrc video, but it does not work.
On the command line it works fine.
"Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg)" will always be False.
Please help me...
send command:
gst-launch-1.0.exe autovideosrc ! videoconvert ! vp8enc deadline=1 ! rtpvp8pay pt=96 ! udpsink port=5200 host=<MY-LOCALIP> async=false
recv command:
gst-launch-1.0.exe udpsrc port=5200 caps="application/x-rtp,payload=(int)96" ! rtpjitterbuffer latency=10 ! rtpvp8depay ! avdec_vp8 output-corrupt=false ! videoconvert ! autovideosink
csharp program:
private void CreatePipeLine()
{
if(pipeline != null)
{
pipeline.SetState(State.Null);
islive = false;
return;
}
pipeline = new Pipeline("pipeline");//"playback");
var udpsrc = Gst.ElementFactory.Make("udpsrc", "source");
udpsrc["port"] = 5200;
//udpsrc["caps"] = "application/x-rtp,payload=96";
var jitter = Gst.ElementFactory.Make("rtpjitterbuffer", "jitter");
jitter["latency"] = 10;
var depay = Gst.ElementFactory.Make("rtpvp8depay", "depay");
var avdec = Gst.ElementFactory.Make("avdec_vp8", "avdec");
avdec["output-corrupt"] = false;
var convert = Gst.ElementFactory.Make("videoconvert", "convert");
var capsRTP = Gst.Global.CapsFromString("application/x-rtp,payload=96");
var mAppSink = new AppSink("appsink");
mAppSink["emit-signals"] = true;
mAppSink["caps"] = capsRTP;
mAppSink.NewSample += OnNewSample;
ink = Gst.ElementFactory.Make("autovideosink", "ink");
pipeline.Add(udpsrc, jitter, depay, avdec, convert, mAppSink); //ink);
udpsrc.Link(jitter);
jitter.Link(depay);
depay.Link(avdec);
avdec.Link(convert);
convert.Link(ink);
Bus bus = pipeline.Bus;
bus.AddSignalWatch();
bus.Message += OnBusMessage;
bus.EnableSyncMessageEmission();
bus.SyncMessage += new SyncMessageHandler(OnBusSynMessage);
/*
VideoSink = new AppSink(ink.Handle);
VideoSink.Drop = true;
VideoSink.MaxLateness = (1000 / 30) * 1000000;
VideoSink.MaxBuffers = 1;
VideoSink.Qos = true;
VideoSink.EnableLastSample = false;
VideoSink.Caps = Gst.Caps.FromString("video/x-raw,format=RGBA");
pipeline.Bus.EnableSyncMessageEmission();
pipeline.Bus.AddSignalWatch();
pipeline.Bus.SyncMessage += OnBusSynMessage;
pipeline.Bus.Message += OnBusMessage;
*/
pipeline.SetState(State.Null);
var ret = pipeline.SetState(State.Ready);
}
private void OnBusSynMessage(object o, SyncMessageArgs sargs)
{
Gst.Message msg = sargs.Message;
if (!Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg)) { return;}
Element src = msg.Src as Element;
if(src == null) { return;}
try { src["force-aspect-ration"] = true;}
catch(PropertyNotFoundException) { }
Element overlay = ((Gst.Bin)src).GetByInterface(VideoOverlayAdapter.GType);
if(overlay == null)
{
System.Diagnostics.Debug.WriteLine($"Overlay is null");
return;
}
_adapter = new VideoOverlayAdapter(overlay.Handle);
_adapter.WindowHandle = _windowHandle;
_adapter.HandleEvents(true);
_isRender = true;
}
Tried this method during playback, but "sample" was null.
var sink = VideoSink;
if(sink == null) { return; }
Sample sample = sink.TryPullSample(5000);
if(sample == null)
{
return;
}
Reference Site:
https://github.com/vladkol/gstreamer-netcore/tree/master/samples/AvaloniaPlayer
how to use application/x-rtp binding with gstreamer-sharp?
I've changed the caps location to udpsrc,
I have tried autovideosink, etc.
Gst.Video.Global.IsVideoOverlayPrepareWindowHandleMessage(msg)
will be not null only if you have autovideosink in your pipeline. This is because a Window creation request will be created if you have Window "VideoSink" like autovideosink, glvideosink... which implements GstVideoOverlay. (https://gstreamer.freedesktop.org/documentation/opengl/glimagesink.html?gi-language=c#hierarchy see implemented interfaces)
pipeline.Add(udpsrc, jitter, depay, avdec, convert, ink);
Why not setting your pipeline to playing instead of ready ?
var ret = pipeline.SetState(State.Playing);
Related
I try to implement processing frames from webcam to the WPF application using UWP API.
There is article how to work with MediaCapture & MediaFrameReader:
https://learn.microsoft.com/en-us/windows/uwp/audio-video-camera/process-media-frames-with-mediaframereader#handle-the-frame-arrived-event
If I set up MemoryPreference to cpu, SoftwareBitmaps are initialized to the null in the event. When I place Auto, I can see IDirect3DSurface objects are in the event, but in conversion to the SoftwareBitmap the exception "Specified cast is not valid." is raised.
How to convert IDirect3DSurface to SoftwareBitmap?
private async void MediaCaptureExample()
{
var frameSourceGroups = await MediaFrameSourceGroup.FindAllAsync();
MediaFrameSourceGroup selectedGroup = null;
MediaFrameSourceInfo colorSourceInfo = null;
foreach (var sourceGroup in frameSourceGroups)
{
foreach (var sourceInfo in sourceGroup.SourceInfos)
{
if (sourceInfo.MediaStreamType == MediaStreamType.VideoRecord && sourceInfo.SourceKind == MediaFrameSourceKind.Color)
{
colorSourceInfo = sourceInfo;
break;
}
}
if (colorSourceInfo != null)
{
selectedGroup = sourceGroup;
break;
}
}
capture = new MediaCapture();
var settings = new MediaCaptureInitializationSettings()
{
SourceGroup = selectedGroup,
SharingMode = MediaCaptureSharingMode.ExclusiveControl,
MemoryPreference = MediaCaptureMemoryPreference.Auto,
StreamingCaptureMode = StreamingCaptureMode.Video
};
await capture.InitializeAsync(settings);
var colorFrameSource = capture.FrameSources[colorSourceInfo.Id];
var preferredFormat = colorFrameSource.SupportedFormats.Where(format =>
{
return format.VideoFormat.Width >= 1080
&& String.Compare(format.Subtype, MediaEncodingSubtypes.Mjpg, true) == 0;
}).FirstOrDefault();
if (preferredFormat == null)
{
// Our desired format is not supported
return;
}
await colorFrameSource.SetFormatAsync(preferredFormat);
mediaFrameReader = await capture.CreateFrameReaderAsync(colorFrameSource);
mediaFrameReader.FrameArrived += MediaFrameReader_FrameArrived;
var result = await mediaFrameReader.StartAsync();
Console.WriteLine("Result = " + result.ToString());
}
private void MediaFrameReader_FrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
try
{
var mediaFrameReference = sender.TryAcquireLatestFrame();
var videoMediaFrame = mediaFrameReference?.VideoMediaFrame;
var softwareBitmap = videoMediaFrame?.SoftwareBitmap;
var direct3DSurface = videoMediaFrame?.Direct3DSurface;
if (direct3DSurface != null)
{
var softwareBitmapTask = SoftwareBitmap.CreateCopyFromSurfaceAsync(mediaFrameReference.VideoMediaFrame.Direct3DSurface).AsTask();
softwareBitmap = softwareBitmapTask.Result;
}
if (softwareBitmap != null)
{
using (var stream = new Windows.Storage.Streams.InMemoryRandomAccessStream())
{
var encoderTask = BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream).AsTask();
encoderTask.Wait();
var encoder = encoderTask.Result;
encoder.SetSoftwareBitmap(softwareBitmap);
Task t = encoder.FlushAsync().AsTask();
t.Wait();
var image = new System.Windows.Media.Imaging.BitmapImage();
image.BeginInit();
image.StreamSource = stream.AsStream();
image.CacheOption = System.Windows.Media.Imaging.BitmapCacheOption.OnLoad;
image.EndInit();
imageElement.Source = image;
}
}
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
The issue was in format subtype. I changed format from Mjpg to Nv12, and everything start working properly (even for MediaCaptureMemoryPreference.Auto):
var preferredFormat = colorFrameSource.SupportedFormats.Where(format =>
{
return format.VideoFormat.Width >= 1080 && String.Compare(format.Subtype, MediaEncodingSubtypes.Nv12, true) == 0;
}).FirstOrDefault();
I've got a method that returning back from CompletionService.GetDescriptionAsync(Document, CompletionItem) gives me the following description:
void SQL.GetSQLiteDB(string url) (+ 1 overload)
This is a method I made on a Xamarin project, here are both method signatures:
public static void GetSQLiteDB(string url);
public static string GetSQLiteDB(string url, string name);
What's the Roslyn way to get information on both?
Here's how I'm setting up completions:
async Task InitCodeCompletion()
{
host = MefHostServices.Create(MefHostServices.DefaultAssemblies);
workspace = new AdhocWorkspace(host);
Type[] types =
{
typeof(object),
typeof(System.Linq.Enumerable),
typeof(System.Collections.IEnumerable),
typeof(Console),
typeof(System.Reflection.Assembly),
typeof(List<>),
typeof(Type),
typeof(SQL)
};
imports = types.Select(x => x.Namespace).Distinct().ToImmutableArray();
assemblies = types.Select(x => x.Assembly).Distinct().ToImmutableArray();
references = assemblies.Select(t => MetadataReference.CreateFromFile(t.Location) as MetadataReference).ToImmutableArray();
compilationOptions = new CSharpCompilationOptions(
OutputKind.DynamicallyLinkedLibrary,
usings: imports);
projectInfo = ProjectInfo.Create(ProjectId.CreateNewId(), VersionStamp.Create(), "Script", "Script", LanguageNames.CSharp, isSubmission: true)
.WithMetadataReferences(references).WithCompilationOptions(compilationOptions);
project = workspace.AddProject(projectInfo);
documentInfo = DocumentInfo.Create(DocumentId.CreateNewId(project.Id), "Script", sourceCodeKind: SourceCodeKind.Script,
loader: TextLoader.From(TextAndVersion.Create(SourceText.From(""), VersionStamp.Create())));
document = workspace.AddDocument(documentInfo);
var services = workspace.Services;
completionService = CompletionService.GetService(document);
}
async Task<CodeCompletionResults> GetCompletions(string code)
{
string codeModified = "using SQL = XamTestNET5.Services.SQLiteGeneratorService; " + Environment.NewLine;
codeModified += "using HtmlSvc = XamTestNET5.Services.HtmlRetrievalService;" + Environment.NewLine;
// ^^^ The above two lines set up some simple namespace aliases in my project, if you know how to put this in a separate project document and use it in code completion please let me know in comments as otherwise doing so gives me an exception that you can't have multiple syntax trees
codeModified += code;
var source = SourceText.From(codeModified);
document = document.WithText(source);
// cursor position is at the end
var position = source.Length;
var completions = await completionService.GetCompletionsAsync(document, position);
return new CodeCompletionResults() { InputCode = code, ModifiedCode = codeModified, Completions = completions };
}
Here's how I'm getting them now and putting them in a browser control:
private async void CSharpShellEnvironment_EntryCodeCompletionEntry(object sender, CSharpShellEnvironment.EntryEventArgs e)
{
if (e.Value != "")
{
CodeCompletionResults results = await GetCompletions(e.Value);
CompletionList list = results.Completions;
if (list != null)
{
if (list.Items != null)
{
StringBuilder sb = new StringBuilder();
foreach (var item in list.Items)
{
string spanText = (item.Span.Start != item.Span.End) ? results.ModifiedCode.Substring(item.Span.Start, item.Span.Length) : "";
bool recommended = spanText == "" ? true : item.DisplayText.StartsWith(spanText);
if (recommended)
{
string fText = item.DisplayText.Substring(spanText.Length);
string props = "";
foreach(var p in item.Properties)
{
props += $"<span data-key=\"{p.Key}\" data-value=\"{p.Value}\"></span>";
}
string tags = "";
foreach(var t in item.Tags)
{
tags += $"<span data-tag=\"{t}\"></span>";
}
string descStr = "";
if (item.Tags != null)
{
if (item.Tags.Where(x => x.ToLower() == "method").FirstOrDefault() != null && item.Tags.Where(x => x.ToLower() == "public").FirstOrDefault() != null)
{
var desc = await completionService.GetDescriptionAsync(document, item);
descStr += $"<span data-desc=\"{desc.Text}\">";
foreach(var part in desc.TaggedParts)
{
descStr += $"<span data-desc-part-tag=\"{part.Tag}\" data-desc-part-text=\"{part.Text}\"></span>";
}
descStr += "</span>";
}
}
sb.AppendLine($"<div class=\"codecompleteentry\" data-display-text=\"{item.DisplayText}\" data-span-text=\"{spanText}\" data-final-text=\"{fText}\">{props}{tags}{descStr}{fText}</div>");
}
}
string scriptInputClick = "Array.prototype.forEach.call(document.getElementsByClassName('codecompleteentry'), function(el) { el.addEventListener('click', function(elem) { var text = { MessageType: 'CodeCompletion', Parameters: JSON.stringify({ DataDisplayText: el.getAttribute('data-display-text'), DataSpanText: el.getAttribute('data-span-text'), DataFinalText: el.getAttribute('data-final-text') }), Message: el.innerText }; window.chrome.webview.postMessage(text); } ); });";
sb.AppendLine($"<script type=\"text/javascript\">{scriptInputClick}</script>");
env.EnterCodeCompletionResponse(sb.ToString());
}
else
{
env.EnterCodeCompletionResponse(strNoSuggestions);
}
}
else
{
env.EnterCodeCompletionResponse(strNoSuggestions);
}
}
else
{
env.EnterCodeCompletionResponse(strNoSuggestions);
}
}
It seems on the surface that CompletionSurface has everything you need, but it doesn't, you need to reference the Document's SemanticModel in order to get all of the signature overloads of a method when the user types ( on a method during code completion.
It wasn't very obvious to me until I started looking through the RoslynPad source, which I recommend doing for a practical example: https://github.com/aelij/RoslynPad
List<IEnumerable<ReferencedSymbol>> allMethodRefs = new List<IEnumerable<ReferencedSymbol>>();
async Task<CodeCompletionResults> GetCompletions(string code)
{
string codeModified = "using SQL = XamTestNET5.Services.SQLiteGeneratorService; " + Environment.NewLine;
codeModified += "using HtmlSvc = XamTestNET5.Services.HtmlRetrievalService;" + Environment.NewLine;
// ^^^ I put my namespace aliases in the same SyntaxTree for now,
// I'd like a better solution though.
codeModified += code;
var source = SourceText.From(codeModified);
document = document.WithText(source);
// cursor position is at the end
var position = source.Length;
var completions = await completionService.GetCompletionsAsync(document, position);
syntaxRoot = await document.GetSyntaxRootAsync();
semanticModel = await document.GetSemanticModelAsync();
var methods = syntaxRoot.DescendantNodes().OfType<InvocationExpressionSyntax>();
allMethodRefs = new List<IEnumerable<ReferencedSymbol>>();
if (methods != null)
{
if (methods.Count() > 0)
{
foreach(var m in methods)
{
var info = semanticModel.GetSymbolInfo(m);
if (info.Symbol != null)
{
allMethodRefs.Add(await SymbolFinder.FindReferencesAsync(info.Symbol, solution));
}
else
{
foreach(var symbol in info.CandidateSymbols)
{
allMethodRefs.Add(await SymbolFinder.FindReferencesAsync(symbol, solution));
}
}
}
}
}
return new CodeCompletionResults() { InputCode = code, ModifiedCode = codeModified, Completions = completions };
}
Has anybody ever had an issue where the SessionModSvcContractClient Logout function throws an Exception: Additional information:
Object reference not set to an instance of an object.
When I tried LogoutAsync and Close methods they worked fine.
Can anybody help me figure out why that's happening or the difference between the 3.
I'm basically trying to use create the test from the WCF guide
static void Main(string[] args)
{
//use a self-signed certificate in IIS, be sure to include the following code. This code speeds up calls to the services and prevents the method from trying to validate the certificate with the known authorities.
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, errors) => { return true; };
//You can toggle the value assigned to this variable to test the two bindings: SOAPHttp or BasicHttp
EndpointBindingType bindingType = EndpointBindingType.SOAPHttp;
//Epicor credentials:
string epicorUserID = "XXX";
string epiorUserPassword = "XXX";
string scheme = "http";
if (bindingType == EndpointBindingType.BasicHttp)
{
scheme = "https";
}
UriBuilder builder = new UriBuilder(scheme, "localhost");
string webServicesLink = "XXX/";
builder.Path = webServicesLink + "Ice/Lib/SessionMod.svc";
SessionModSvcContractClient sessionModClient = GetClient < SessionModSvcContractClient, SessionModSvcContract > (builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);
builder.Path = webServicesLink + "Erp/BO/AbcCode.svc";
ABCCodeSvcContractClient abcCodeClient = GetClient<ABCCodeSvcContractClient, ABCCodeSvcContract>(builder.Uri.ToString(), epicorUserID, epiorUserPassword, bindingType);
Guid sessionId = Guid.Empty;
sessionId = sessionModClient.Login();
//Create a new instance of the SessionModSvc. Do this because when you call any method on the service
//client class, you cannot modify its Endpointbehaviors.
builder.Path = webServicesLink + "Ice/Lib/SessionMod.svc";
sessionModClient = GetClient < SessionModSvcContractClient, SessionModSvcContract > (builder.Uri.ToString(),epicorUserID,epiorUserPassword,bindingType);
sessionModClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));
abcCodeClient.Endpoint.EndpointBehaviors.Add(new HookServiceBehavior(sessionId, epicorUserID));
var ts = new ABCCodeTableset();
abcCodeClient.GetNewABCCode(ref ts);
var newRow = ts.ABCCode.Where(n => n.RowMod.Equals("A", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
if (newRow != null)
{
newRow.ABCCode = "G";
newRow.CountFreq = 30;
newRow.StockValPcnt = 100;
abcCodeClient.Update(ref ts);
ts = null;
ts = abcCodeClient.GetByID("G");
if (ts != null && ts.ABCCode.Any())
{
ABCCodeRow backupRow = new ABCCodeRow();
var fields = backupRow.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
foreach (var field in fields)
{
if (field.PropertyType == typeof(System.Runtime.Serialization.ExtensionDataObject))
{
continue;
}
var fieldValue = field.GetValue(ts.ABCCode[0]);
field.SetValue(backupRow, fieldValue);
}
ts.ABCCode.Add(backupRow);
ts.ABCCode[0].CountFreq = 45;
ts.ABCCode[0].RowMod = "U";
abcCodeClient.Update(ref ts);
ts = null;
ts = abcCodeClient.GetByID("G");
if (ts != null && ts.ABCCode.Any())
{
Console.WriteLine("CountFreq = {0}", ts.ABCCode[0].CountFreq);
ts.ABCCode[0].RowMod = "D";
abcCodeClient.Update(ref ts);
try
{
ts = abcCodeClient.GetByID("G");
}
catch (FaultException<Epicor.AbcCodeSvc.EpicorFaultDetail> ex)
{
if (ex.Detail.ExceptionKindValue.Equals("RecordNotFound", StringComparison.InvariantCultureIgnoreCase))
{
Console.WriteLine("Record deleted.");
}
else
{
Console.WriteLine(ex.Message);
}
}
}
}
}
if (sessionId != Guid.Empty)
{
sessionModClient.Logout();
}
Console.ReadLine();
}
Your code worked fine for me after I changed the config to suit my environment.
It looks like you followed the step 7 on page 15 of the Epicor10_techrefWCFServices_101400.pdf guide and correctly created a new instance of the SessionModSvc after Login(). However, if you copied the full code for the Main method from page 18 then this is missing and I can replicate your issue.
Check the code that you are compiling has created a new instance of the SessionModSvc after the call to .Login().
See my other answer, but as an alternative you may want to consider this method of accessing the services.
If you have access to the client DLLs then this code might be easier:
static void Main(string[] args)
{
// Hard-coded LogOn method
// Reference: Ice.Core.Session.dll
Ice.Core.Session session = new Ice.Core.Session("manager", "manager", "net.tcp://AppServer/MyCustomerAppserver-99999-10.0.700.2");
// References: Epicor.ServiceModel.dll, Erp.Contracts.BO.ABCCode.dll
var abcCodeBO = Ice.Lib.Framework.WCFServiceSupport.CreateImpl<Erp.Proxy.BO.ABCCodeImpl>(session, Erp.Proxy.BO.ABCCodeImpl.UriPath);
// Call the BO methods
var ds = abcCodeBO.GetByID("A");
var row = ds.ABCCode[0];
System.Console.WriteLine("CountFreq is {0}", row.CountFreq);
System.Console.ReadKey();
}
Just add references to:
Ice.Core.Session.dll
Epicor.ServiceModel.dll
Erp.Contracts.BO.ABCCode.dll
I get this error whenever I try to deserialize a protobuf byte array... My code follows:
public void GetFloatValue(ulong sid64, string ilink)
{
string param_s = null;
string param_a = null;
string param_d = null;
string param_m = null;
bool goodlink = false;
bool isinv = false;
CallbackManager Manager = new CallbackManager(SteamClient);
new Callback<SteamGameCoordinator.MessageCallback>(onFloatCallback, Manager);
var Msg = new ClientGCMsgProtobuf<CMsgGCCStrike15_v2_Client2GCEconPreviewDataBlockRequest>((uint)ECsgoGCMsg.k_EMsgGCCStrike15_v2_Client2GCEconPreviewDataBlockRequest);
if (ilink.Contains("steam://rungame/730") && ilink.Contains("%20S7656"))
{
param_s = ilink.Substring(67, 84 - 67);
param_a = ilink.Substring(85, 95 - 85);
param_d = ilink.Substring(96, 115 - 96);
goodlink = true;
isinv = true;
}
else if (ilink.Contains("steam://rungame/730"))
{
param_m = ilink.Substring(67, 85 - 67);
param_a = ilink.Substring(86, 96 - 86);
param_d = ilink.Substring(97, 116 - 97);
goodlink = true;
isinv = false;
}
else
{
goodlink = false;
}
if (goodlink == false)
{
SteamFriends.SendChatMessage(sid64, EChatEntryType.ChatMsg, "Error: Bad Inspect Link");
}
else if (goodlink == true)
{
if (isinv == true)
{
Msg.Body.param_a = Convert.ToUInt64(param_a);
Msg.Body.param_d = Convert.ToUInt64(param_d);
Msg.Body.param_s = Convert.ToUInt64(param_s);
}
else
{
Msg.Body.param_a = Convert.ToUInt64(param_a);
Msg.Body.param_d = Convert.ToUInt64(param_d);
Msg.Body.param_m = Convert.ToUInt64(param_m);
}
var playGame = new ClientMsgProtobuf<CMsgClientGamesPlayed>(EMsg.ClientGamesPlayed);
playGame.Body.games_played.Add(new CMsgClientGamesPlayed.GamePlayed
{
game_id = new GameID(730),
});
SteamClient.Send(playGame);
var clientHello = new ClientGCMsgProtobuf<CMsgClientHello>((uint)EGCBaseClientMsg.k_EMsgGCClientHello);
SteamGameCoordinator.Send(clientHello, 730);
SteamGameCoordinator.Send(Msg, 730);
Manager.RunWaitCallbacks(TimeSpan.FromSeconds(1));
}
}
public void onFloatCallback(SteamGameCoordinator.MessageCallback callback)
{
byte[] bytes = callback.Message.GetData();
MemoryStream stream = new MemoryStream(bytes);
var obj = ProtoBuf.Serializer.Deserialize<CEconItemPreviewDataBlock>(stream);
Console.WriteLine(obj.origin);
}
The error in the console includes multiple lines where the error is occurring, a few of them are in the protobuf-net class files, but the first one that actually includes a line of my code is on the line that has var obj = ProtoBuf.Serializer.Deserialize<CEconItemPreviewDataBlock>(stream); the next one is at Manager.RunWaitCallbacks(TimeSpan.FromSeconds(1));
I'm having the difficulties to use watin bringtofront function. It just doesn't bring my browser to the front - someone please shed me some light on it.
Here's my code:
public bool GenerateReport(string rptPath, string rptName)
{
var popupTitle = new Regex("Crystal Reports ActiveX");
var popUpBrowser = WatiN.Core.Browser.AttachTo<IE>(Find.ByTitle(popupTitle));
if (popUpBrowser != null)
{
var result = false;
try
{
popUpBrowser.AutoClose = false;
popUpBrowser.BringToFront();
popUpBrowser.ShowWindow(NativeMethods.WindowShowStyle.ShowMaximized);
popUpBrowser.DialogWatcher.CloseUnhandledDialogs = false;
result = ExportPdfFile(popUpBrowser, rptPath + rptName + RptExt);
}
finally
{
popUpBrowser.Close();
}
return result;
}
return false;
}