I have developed a Managed Browser Helper Object (BHO). This works on all machines except one.
I have ensured that protected mode is off and UAC is also turned off on this machine.
This particular machine is Win Vista with IE 8.
I added some debug logs and message box in GetSite and Setsite. I do not see these logs or message box. I am assuming that these are not being called for some reason.
Is there some better way to debug my problem?
Thanks
Once it happens to me when I entered wrong COM object GUID. In 'must-have' interface 'IObjectWithSite' the definition must-be as follows:
/// <summary>
/// Interface to hook into IE
/// </summary>
[
ComImport(),
ComVisible(true),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352") // Defined here: http://msdn.microsoft.com/en-us/library/aa768186(v=vs.85).aspx
]
interface IObjectWithSite
{
/// <summary>
/// Function will register our program with actual browser
/// </summary>
/// <param name="pUnkSite"></param>
/// <returns></returns>
//[PreserveSig]
void SetSite([In, MarshalAs(UnmanagedType.IUnknown)] object pUnkSite);
/// <summary>
/// Callers invoke this to retrieve the container site previously sent to SetSite().
/// This implementation handles the return of appropriate HRESULT per the
/// documented interface requirements for IObjectWithSite.
/// </summary>
/// <param name="riid">GUID for the interface requested of the site object</param>
/// <param name="ppvSite">Fill this with the site object if we find the interface through QI call</param>
void GetSite(ref Guid riid, [MarshalAs(UnmanagedType.IUnknown)] out object ppvSite);
}//interface close
But since you sad that only one machine doesn't support it...
Related
I'm using the MSFT Bot Framework to build a team bot but my bot is only relevant to my organization. Actually I don't want anyone outside my organization to be able to talk to it.
I've been looking how to limit my bot to a specific Office 365 organization but can't find how to do it. The only thing I can find is using the other party userstring to see in which org they live.
My question:
Is ther a way to limit my bot to a single O365 organization?
Thanks
Bram
Its been 2 years but there's no real answer and it popped up in my related list tho...
These days you can write an easy simple middleware that does the tenant filtering like here:
public static string TenantFilterSettingAny = "#ANY#";
/// <summary>
/// Here are below scenarios -
/// #Scenario 1 - Reject the Bot If Tenant is configured in web.config and doesn't match with Incoming request tenant
/// #Scenario 2 - Allow Bot for every Tenant if Tenant is not configured in web.config file and default value is #ANY#
/// </summary>
/// <param name="activity"></param>
/// <param name="currentTenant"></param>
/// <returns></returns>
public static bool RejectMessageBasedOnTenant(IMessageActivity activity, string currentTenant)
{
if (!String.Equals(ConfigurationManager.AppSettings["OFFICE_365_TENANT_FILTER"], TenantFilterSettingAny))
{
//#Scenario 1
return !string.Equals(ConfigurationManager.AppSettings["OFFICE_365_TENANT_FILTER"], currentTenant);
}
else
{
//Scenario 2
return false;
}
}
Its taken from this sample
The most reliable way right now is to implement authentication of users, as demonstrated in AuthBot, and then check the tenant-id of the logged-in user.
I'm playing with Google Drive's API and I would know if I need to do the code bellow each time I need to use the API:
import "package:googleapis_auth/auth_browser.dart" as gauth;
import "package:googleapis/drive/v2.dart" as drive;
...
var clientid = new gauth.ClientId("xxx.apps.googleusercontent.com", null);
var scope = [drive.DriveApi.DriveScope];
gauth.createImplicitBrowserFlow(clientid, scope).then((gauth.BrowserOAuth2Flow flow) {
flow.clientViaUserConsent().then((gauth.AutoRefreshingAuthClient client) {
var drive_api = new drive.DriveApi(client);
// My code here.
}).catchError((e) => print(e));
});
...
Once client var generated, there is no way to recover it without to do these code lines each time?
I personally save the variable you called drive_api globally (in memory) and reuse it in my application (i.e. my webapp so yes it will run again when you reload the page). Some errors (I guess when the token needs to be refreshed, or if the permissions are revoked) might require you to re-run the whole flow. I think the trick is to run it "silently" after the page is loaded
flow.clientViaUserConsent(immediate: true)
by doing so, your "drive_api" variable will be loaded if the user already granted permission in previous sessions. For example I typically enable some buttons at this point
and if it fails (i sometimes add a "login button"), explicitly call (better do that on "on-click" to allow popup to appear)
flow.clientViaUserConsent()
Some doc for the immediate parameter:
/// If [immediate] is `true` there will be no user involvement. If the user
/// is either not logged in or has not already granted the application access,
/// a `UserConsentException` will be thrown.
///
/// If [immediate] is `false` the user might be asked to login (if he is not
/// already logged in) and might get asked to grant the application access
/// (if the application hasn't been granted access before).
I've added Coded UI Tests to my ASP.NET MVC solution in Visual Studio 2013. I was dismayed to see how slowly the tests run; each page just sits there for up to a minute or more before the test machinery wakes up and starts filling in the form fields.
After some experimentation (including turning off SmartMatch), I've discovered that simply calling
Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.Disabled;
solves the problem. But, as expected, the test frequently fails because the UI thread isn't ready for the test machinery to interact with the controls on the form.
Calling
Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.UIThreadOnly;
makes the test run reliably, if slowly.
Any thoughts or suggestions? Any hope that someone might have some insight into the magic baked into the WaitForReady machinery? Are there any other settings related to WaitForReady that I can fiddle with besides WaitForReadyLevel?
After a bit of experimentation, I've worked out what appears to be a combination of settings that allows my Coded UI Tests to reliably run at full speed -- faster than I could interact with the website by hand.
Note: The relevant "documentation" (if you call a blog "documentation") can be found here:
Playback configuration settings
Retrying failed playback actions.
The trick requires several modifications to the default playback settings:
Setting WaitForReadyLevel = WaitForReadyLevel.Disabled allows the test to run at full speed. But it also disables the (slow!) magic that waits until it's safe to interact with controls on the page.
Setting a MaximumRetryCount and attaching an error handler deals with most of the errors that result from disabling the "wait for ready" magic. Because I've baked a 1 second Sleep into the retry logic, this value is effectively the number of seconds I'm willing to wait for the page to load and become responsive.
Apparently, failure to find the control under test is not one of the errors handled by the error handler/retry mechanism. If the new page takes more than a few seconds to load, and the test is looking for a control that doesn't exist until the new page loads, the test fails to find the control and the test fails. Setting ShouldSearchFailFast = false solves that problem by giving you the full timeout time for your page to load.
Setting DelayBetweenActions = 500 appears to work around a problem that I see occasionally where the UI misses a button click that occurs immediately after a page has loaded. The test machinery seems to think that the button was clicked, but the web page doesn't respond to it.
The "documentation" says that the default search timeout is 3 minutes, but it's actually something greater than 10 minutes, so I explicitly set SearchTimeout to 1 second (1000 ms).
To keep all of the code in one place, I've created a class that contains code used by all of the tests. MyCodedUITests.StartTest() is called by the [TestInitialize] method in each of my test classes.
This code really should be executed only once for all of the tests (rather than once per test), but I couldn't figure out a way to get the Playback.PlaybackSettings calls to work in the [AssemblyInitialization] or [ClassInitialization] routines.
/// <summary> A class containing Coded UI Tests. </summary>
[CodedUITest]
public class UI_Tests
{
/// <summary> Common initialization for all of the tests in this class. </summary>
[TestInitialize]
public void TestInit()
{
// Call a common routine to set up the test
MyCodedUITests.StartTest();
}
/// <summary> Some test. </summary>
[TestMethod]
public void SomeTest()
{
this.UIMap.Assert_HomePageElements();
this.UIMap.Recorded_DoSomething();
this.UIMap.Assert_FinalPageElements();
}
}
/// <summary> Coded UI Test support routines. </summary>
class MyCodedUITests
{
/// <summary> Test startup. </summary>
public static void StartTest()
{
// Configure the playback engine
Playback.PlaybackSettings.WaitForReadyLevel = WaitForReadyLevel.Disabled;
Playback.PlaybackSettings.MaximumRetryCount = 10;
Playback.PlaybackSettings.ShouldSearchFailFast = false;
Playback.PlaybackSettings.DelayBetweenActions = 500;
Playback.PlaybackSettings.SearchTimeout = 1000;
// Add the error handler
Playback.PlaybackError -= Playback_PlaybackError; // Remove the handler if it's already added
Playback.PlaybackError += Playback_PlaybackError; // Ta dah...
}
/// <summary> PlaybackError event handler. </summary>
private static void Playback_PlaybackError(object sender, PlaybackErrorEventArgs e)
{
// Wait a second
System.Threading.Thread.Sleep(1000);
// Retry the failed test operation
e.Result = PlaybackErrorOptions.Retry;
}
}
Coded UI searches for controls on the screen and that search is quite fast if successful. However if the search fails then Coded UI has another try using a "smart match" method and that can be slow. The basic way of avoiding Coded UI falling back to using smart matching is to remove or simplify search items that may change from run to run.
This Microsoft blog gives lots of explanation of what happens and how to fix it. The example therein shows a speedup from 30 seconds to 8 seconds by changing a search string from
Name EqualsTo “Sales order (1 - ceu) - Sales order: SO-101375, Forest Wholesales”
to
Name Contains “Sales order (1 - ceu) - Sales order: SO”
Seems like it is captured from microsoft dynamics tool. Please check the length of the string captured from inspect tool. You will be finding some hidden character. just order (1 - ceu). Else just move the cursor from "(" to ")". You will be finding cursor is not moving sometime when pressing right arrow key.
While trying to understand how Navision 5 can communicate with an external application through COM interop, i found the following example:
http://msdn.microsoft.com/en-us/library/aa973247.aspx
The second case implemented is exactly what I want to do. I tested the code (with minor modifications - added some attributes [ComVisible(true)] on the events interface and class) and with these modifications it worked as stated in the example.
However, I cannot understand why we do not get an exception on invoking the COMTimer.Elapsed through the following.
protected virtual void OnElapsed(EventArgs e)
{
Elapsed();
}
Who is hooked to this event? The only "hook" i can see is the mTimer.Elapsed += new ElapsedEventHandler(mTimer_Elapsed); that refers to the Elapsed event of the mTimer.
Normally, Elapsed would be null in the OnElapsed function.
I would appreciate your help. Thanks in advance.
Interesting problem.
WithEvents property on automation creates the handler and attaches it to Elapsed delegate, so this one is not NULL - hence no exception
However, when WithEvents is No, and Timer.Start() is invoked, as you rightly say no exception bubbles up, even though (in theory) Elapsed delegate is null.
The simple explanation to this would be, that NAV attaches empty delegate regardless of WithEvents property. To support that, if you put code in Timer::Elapsed() trigger, then take off WithEvents, and bring it back - the code will still be there (i.e. trigger still exists in unchanged form), which makes me lean towards conclusion that it exists always (i.e. empty delegate).
But of course it's NAV so it couldn't be that simple.
I created a test codeunit from above MSDN example, but made a small change to the automation:
/// <summary>
/// Whenever the internal timer elapses, an event must be fired
/// </summary>
private void mTimer_Elapsed(object sender, ElapsedEventArgs e)
{
OnElapsed(EventArgs.Empty);
throw null;
}
This, in theory, should throw NULL whenever mTimer_Elapsed is invoked - nothing however bubbles up in NAV. I went a bit further and changed this:
///<summary>
/// Invoke the Changed event; called whenever the internal timer elapses
/// </summary>
protected virtual void OnElapsed(EventArgs e)
{
throw new InvalidCastException("test");
//Elapsed();
}
Again, nothing happens in NAV.
Note, that both changes behave as expected if the COM Timer is consumed from within .NET project. This makes me think, that NAV Interop must be capturing exceptions from the automation and handle them internally.
I would however pop that question in Mibuso - someone there will probably know better.
Is there a way my program can determine when it's running on a Remote Desktop (Terminal Services)?
I'd like to enable an "inactivity timeout" on the program when it's running on a Remote Desktop session. Since users are notorious for leaving Remote Desktop sessions open, I want my program to terminate after a specified period of inactivity. But, I don't want the inactivity timeout enabled for non-RD users.
GetSystemMetrics(SM_REMOTESESSION) (as described in http://msdn.microsoft.com/en-us/library/aa380798.aspx)
Here's the C# managed code i use:
/// <summary>
/// Indicates if we're running in a remote desktop session.
/// If we are, then you MUST disable animations and double buffering i.e. Pay your taxes!
///
/// </summary>
/// <returns></returns>
public static Boolean IsRemoteSession
{
//This is just a friendly wrapper around the built-in way
get
{
return System.Windows.Forms.SystemInformation.TerminalServerSession;
}
}
The following works if you want to know about YOUR application which is running in YOUR session:
BOOL IsRemoteSession(void)
{
return GetSystemMetrics( SM_REMOTESESSION );
}
But not in general for any process ID.
If you want to know about any arbitrary process which could be running in any arbitrary session then you can use the below method.
You can first convert the process ID to a session ID by calling ProcessIdToSessionId. Once you have the session ID you can use it to call: WTSQuerySessionInformation. You can specify WTSInfoClass as value WTSIsRemoteSession and this will give you the information about if that application is a remote desktop connection or not.
BOOL IsRemoteSession(DWORD sessionID)
{
//In case WTSIsRemoteSession is not defined for you it is value 29
return WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionID, WTSIsRemoteSession, NULL, NULL);
}