Git Product home page Git Product logo

Comments (3)

matthewacme avatar matthewacme commented on July 29, 2024

here is the code corrected as best I can to get it to work (sort of) (see the note in the Static class where the CoWaitForMultipleObjects function is called)

I got rid of the static on the code that attempts to assign the event handler , and added a utility class for the COM calls.

	private bool DecideRedirection( string key )
	{
		bool isRedirect = false;

		// Find out what kind of activation this is.
		AppActivationArguments args = AppInstance.GetCurrent().GetActivatedEventArgs();
		ExtendedActivationKind kind = args.Kind;
		if ( kind == ExtendedActivationKind.Launch )
		{
			try
			{
				AppInstance keyInstance = AppInstance.FindOrRegisterForKey( key );

				// If we successfully registered the file name, we must be the
				// only instance running that was activated for this file.
				if ( keyInstance.IsCurrent )
				{
					// Hook up the Activated event, to allow for this instance of the app
					// getting reactivated as a result of multi-instance redirection.
					keyInstance.Activated += OnKeyInstanceActivated;
				}
				else
				{
					isRedirect = true;

					Utility.HandleWaiterInterop waiter = new HandleWaiterInterop();

					// Ensure we don't block the STA, by doing the redirect operation
					// in another thread, and using an event to signal when it has completed.
					var redirectEventHandle = HandleWaiterInterop.CreateEvent( IntPtr.Zero , true , false , null );
					if ( redirectEventHandle != IntPtr.Zero )
					{
						Task.Run( () =>
						{
							keyInstance.RedirectActivationToAsync( args ).AsTask().Wait();
							HandleWaiterInterop.SetEvent( redirectEventHandle );
						} );

						HandleWaiterInterop.WaitForHandles( new nint[] { redirectEventHandle } );
					}
				}
			}
			catch ( Exception ex )
			{
				Debug.WriteLine( $"Error getting instance information: {ex.Message}" );
			}
		}

		return isRedirect;
	}

and to support the com calls, I included this utility class

public class HandleWaiterInterop
{
	// Import the CoWaitForMultipleObjects function from combase.dll
	[DllImport( "combase.dll" , SetLastError = true )]
	public static extern int CoWaitForMultipleObjects(
		 uint dwFlags ,
		 uint dwTimeout ,
		 uint cHandles ,
		 IntPtr pHandles ,
		 out uint lpdwIndex
	);

	[DllImport( "kernel32.dll" , SetLastError = true )]
	public static extern IntPtr CreateEvent(
		IntPtr lpEventAttributes ,
		bool bManualReset ,
		bool bInitialState ,
		string lpName
	);

	[DllImport( "kernel32.dll" , SetLastError = true )]
	public static extern bool SetEvent( IntPtr hEvent );

	// Wait for multiple handles using CoWaitForMultipleObjects
	public static void WaitForHandles( IntPtr[] handles )
	{
		uint index;
		try
		{

			// NOTE: according to MS documentation at
			// https://github.com/MicrosoftDocs/windows-dev-docs/blob/docs/hub/apps/windows-app-sdk/applifecycle/applifecycle-instancing.md
			// this should work... but it doesn't it throws an error with a memory violation.
			// at least it does inside Visual Studio when run in debug, so could be VS's fault

			int result = CoWaitForMultipleObjects( 0 ,  // Flags (0 for default behavior)
															  ( uint )0xFFFFFFFF ,  // Timeout in milliseconds
															  ( uint )handles.Length ,
															  handles[ 0 ] ,
															  out index );

			if ( result == 0 )
			{
				Console.WriteLine( $"Handle at index {index} signaled." );
			}
			else
			{
				Console.WriteLine( "Wait failed or timed out." );
			}
		}
		catch ( Exception ex )
		{
			// we crashed, so do nothing
		}
	}
}

from windows-dev-docs.

matthewacme avatar matthewacme commented on July 29, 2024

Mind you when the CoWaitForMultipleObjects function is called the following error is raised, so something is still not right.

But since I only see this error in Visual Studio and when run in release mode, it appears to work... maybe it just doesn't like doing Debug with the COM calls in Visual Studio.

System.AccessViolationException
HResult=0x80004003
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=
StackTrace:

from windows-dev-docs.

matthewacme avatar matthewacme commented on July 29, 2024

Okay, so I referenced the code in

https://github.com/microsoft/WindowsAppSDK-Samples/blob/62316b1f7db932477d4a3811afb0bdaf91ae614b/Samples/AppLifecycle/Instancing/cs2/cs-winui-packaged/CsWinUiDesktopInstancing/CsWinUiDesktopInstancing/Program.cs#L151

and modified my wait procedure to the following (and was able to delete the Static utility class that I was using to pull in the COM calls

	private bool DecideRedirection( string key )
	{
		bool isRedirect = false;

		// Find out what kind of activation this is.
		AppActivationArguments args = AppInstance.GetCurrent().GetActivatedEventArgs();
		ExtendedActivationKind kind = args.Kind;
		if ( kind == ExtendedActivationKind.Launch )
		{
			try
			{
				AppInstance keyInstance = AppInstance.FindOrRegisterForKey( key );

				// If we successfully registered the file name, we must be the
				// only instance running that was activated for this file.
				if ( keyInstance.IsCurrent )
				{
					// Hook up the Activated event, to allow for this instance of the app
					// getting reactivated as a result of multi-instance redirection.
					keyInstance.Activated += OnKeyInstanceActivated;
				}
				else
				{
					isRedirect = true;

					//Utility.HandleWaiterInterop waiter = new HandleWaiterInterop();

					// Ensure we don't block the STA, by doing the redirect operation
					// in another thread, and using an event to signal when it has completed.
					var redirectSemphore = new Semaphore( 0 , 1 );
					Task.Run( () =>
					{
						keyInstance.RedirectActivationToAsync( args ).AsTask().Wait();
						redirectSemphore.Release();
					} );
					redirectSemphore.WaitOne();

				}
			}
			catch ( Exception ex )
			{
				Debug.WriteLine( $"Error getting instance information: {ex.Message}" );
			}
		}

		return isRedirect;
	}

and that seems to work with no errors.

from windows-dev-docs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.